Implement shouldComponentUpdate for LinesComponent

We accumulate pending changes and pass them to the lines and the gutter
to help them determine whether to update. The lines only update if the
visible row range changed or if there was a change in the visible row
range.
This commit is contained in:
Nathan Sobo
2014-04-16 12:19:18 -06:00
parent d678f367db
commit 5a9a3c62e1
4 changed files with 21 additions and 19 deletions

View File

@@ -28,10 +28,10 @@ EditorComponent = React.createClass
className += ' is-focused' if focused
div className: className, style: {fontSize, lineHeight, fontFamily}, tabIndex: -1, onFocus: @onFocus,
GutterComponent({editor, visibleRowRange, scrollTop})
GutterComponent({editor, visibleRowRange, scrollTop, @pendingChanges})
EditorScrollViewComponent {
ref: 'scrollView', editor, visibleRowRange, @onInputFocused, @onInputBlurred
ref: 'scrollView', editor, visibleRowRange, @pendingChanges, @onInputFocused, @onInputBlurred
cursorBlinkPeriod, cursorBlinkResumeDelay, showIndentGuide, fontSize, fontFamily, lineHeight
}
@@ -58,6 +58,7 @@ EditorComponent = React.createClass
cursorBlinkResumeDelay: 200
componentDidMount: ->
@pendingChanges = []
@props.editor.manageScrollPosition = true
@listenForDOMEvents()
@@ -72,6 +73,7 @@ EditorComponent = React.createClass
@stopBlinkingCursors()
componentDidUpdate: ->
@pendingChanges.length = 0
@props.parentView.trigger 'editor:display-updated'
observeEditor: ->
@@ -272,9 +274,10 @@ EditorComponent = React.createClass
if updateRequested
@forceUpdate()
onScreenLinesChanged: ({start, end}) ->
onScreenLinesChanged: (change) ->
{editor} = @props
@requestUpdate() if editor.intersectsVisibleRowRange(start, end + 1) # TODO: Use closed-open intervals for change events
@pendingChanges.push(change)
@requestUpdate() if editor.intersectsVisibleRowRange(change.start, change.end + 1) # TODO: Use closed-open intervals for change events
onSelectionAdded: (selection) ->
{editor} = @props

View File

@@ -12,7 +12,7 @@ EditorScrollViewComponent = React.createClass
render: ->
{editor, fontSize, fontFamily, lineHeight, showIndentGuide, cursorBlinkPeriod, cursorBlinkResumeDelay} = @props
{visibleRowRange, onInputFocused, onInputBlurred} = @props
{visibleRowRange, pendingChanges, onInputFocused, onInputBlurred} = @props
contentStyle =
height: editor.getScrollHeight()
WebkitTransform: "translate(#{-editor.getScrollLeft()}px, #{-editor.getScrollTop()}px)"
@@ -28,7 +28,7 @@ EditorScrollViewComponent = React.createClass
div className: 'scroll-view-content', style: contentStyle, onMouseDown: @onMouseDown,
CursorsComponent({editor, cursorBlinkPeriod, cursorBlinkResumeDelay})
LinesComponent({ref: 'lines', editor, fontSize, fontFamily, lineHeight, visibleRowRange, showIndentGuide})
LinesComponent({ref: 'lines', editor, fontSize, fontFamily, lineHeight, visibleRowRange, pendingChanges, showIndentGuide})
div className: 'underlayer',
SelectionsComponent({editor})

View File

@@ -41,10 +41,6 @@ GutterComponent = React.createClass
div className: 'spacer', key: 'bottom-spacer', style: {height: followingHeight}
]
componentDidMount: ->
@pendingChanges = []
@subscribe @props.editor, 'screen-lines-changed', @onScreenLinesChanged
componentWillUnmount: ->
@unsubscribe()
@@ -52,22 +48,16 @@ GutterComponent = React.createClass
# non-zero-delta change to the screen lines has occurred within the current
# visible row range.
shouldComponentUpdate: (newProps) ->
{visibleRowRange, scrollTop} = @props
{visibleRowRange, pendingChanges, scrollTop} = @props
return true unless newProps.scrollTop is scrollTop
return true unless isEqual(newProps.visibleRowRange, visibleRowRange)
for change in @pendingChanges when change.screenDelta > 0 or change.bufferDelta > 0
for change in pendingChanges when change.screenDelta > 0 or change.bufferDelta > 0
return true unless change.end <= visibleRowRange.start or visibleRowRange.end <= change.start
false
componentDidUpdate: ->
@pendingChanges.length = 0
onScreenLinesChanged: (change) ->
@pendingChanges.push(change)
LineNumberComponent = React.createClass
displayName: 'LineNumberComponent'

View File

@@ -1,6 +1,6 @@
React = require 'react'
{div, span} = require 'reactionary'
{debounce, isEqualForProperties, multiplyString} = require 'underscore-plus'
{debounce, isEqual, isEqualForProperties, multiplyString} = require 'underscore-plus'
{$$} = require 'space-pen'
DummyLineNode = $$(-> @div className: 'line', style: 'position: absolute; visibility: hidden;', => @span 'x')[0]
@@ -28,6 +28,15 @@ LinesComponent = React.createClass
@measuredLines = new WeakSet
@updateModelDimensions()
shouldComponentUpdate: (newProps) ->
return true unless isEqualForProperties(newProps, @props, 'visibleRowRange', 'fontSize', 'fontFamily', 'lineHeight', 'showIndentGuide')
{visibleRowRange, pendingChanges} = newProps
for change in pendingChanges
return true unless change.end <= visibleRowRange.start or visibleRowRange.end <= change.start
false
componentDidUpdate: (prevProps) ->
@updateModelDimensions() unless isEqualForProperties(prevProps, @props, 'fontSize', 'fontFamily', 'lineHeight')
@clearScopedCharWidths() unless isEqualForProperties(prevProps, @props, 'fontSize', 'fontFamily')