Assign line width explicitly to prevent full screen repaints

Fixes #2746
This commit is contained in:
Nathan Sobo 2014-06-25 19:13:50 -06:00
parent 95242c8c82
commit 3bf0c73170
3 changed files with 39 additions and 11 deletions

View File

@ -153,6 +153,31 @@ describe "EditorComponent", ->
linesNode = node.querySelector('.lines')
expect(linesNode.offsetHeight).toBe 300
it "assigns the width of each line so it extends across the full width of the editor", ->
gutterWidth = node.querySelector('.gutter').offsetWidth
scrollViewNode = node.querySelector('.scroll-view')
lineNodes = node.querySelectorAll('.line')
node.style.width = gutterWidth + (30 * charWidth) + 'px'
component.measureScrollView()
runSetImmediateCallbacks()
expect(editor.getScrollWidth()).toBeGreaterThan scrollViewNode.offsetWidth
# At the time of writing, using width: 100% to achieve the full-width
# lines caused full-screen repaints after switching away from an editor
# and back again Please ensure you don't cause a performance regression if
# you change this behavior.
for lineNode in lineNodes
expect(lineNode.style.width).toBe editor.getScrollWidth() + 'px'
node.style.width = gutterWidth + editor.getScrollWidth() + 100 + 'px'
component.measureScrollView()
runSetImmediateCallbacks()
scrollViewWidth = scrollViewNode.offsetWidth
for lineNode in lineNodes
expect(lineNode.style.width).toBe scrollViewWidth + 'px'
describe "when showInvisibles is enabled", ->
invisibles = null

View File

@ -68,6 +68,7 @@ EditorComponent = React.createClass
lineHeightInPixels = editor.getLineHeightInPixels()
defaultCharWidth = editor.getDefaultCharWidth()
scrollViewHeight = editor.getHeight()
lineWidth = Math.max(scrollWidth, editor.getWidth())
horizontalScrollbarHeight = editor.getHorizontalScrollbarHeight()
verticalScrollbarWidth = editor.getVerticalScrollbarWidth()
verticallyScrollable = editor.verticallyScrollable()
@ -106,7 +107,7 @@ EditorComponent = React.createClass
editor, lineHeightInPixels, defaultCharWidth, lineDecorations, highlightDecorations,
showIndentGuide, renderedRowRange, @pendingChanges, scrollTop, scrollLeft,
@scrollingVertically, scrollHeight, scrollWidth, mouseWheelScreenRow, invisibles,
visible, scrollViewHeight, @scopedCharacterWidthsChangeCount
visible, scrollViewHeight, @scopedCharacterWidthsChangeCount, lineWidth
}
ScrollbarComponent

View File

@ -39,7 +39,7 @@ LinesComponent = React.createClass
return true unless isEqualForProperties(newProps, @props,
'renderedRowRange', 'lineDecorations', 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth',
'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'invisibles', 'visible',
'scrollViewHeight', 'mouseWheelScreenRow', 'scopedCharacterWidthsChangeCount'
'scrollViewHeight', 'mouseWheelScreenRow', 'scopedCharacterWidthsChangeCount', 'lineWidth'
)
{renderedRowRange, pendingChanges} = newProps
@ -54,20 +54,20 @@ LinesComponent = React.createClass
@clearScreenRowCaches() unless prevProps.lineHeightInPixels is @props.lineHeightInPixels
@removeLineNodes() unless isEqualForProperties(prevProps, @props, 'showIndentGuide', 'invisibles')
@updateLines()
@updateLines(@props.lineWidth isnt prevProps.lineWidth)
@measureCharactersInNewLines() if visible and not scrollingVertically
clearScreenRowCaches: ->
@screenRowsByLineId = {}
@lineIdsByScreenRow = {}
updateLines: ->
updateLines: (updateWidth) ->
{editor, renderedRowRange, showIndentGuide, selectionChanged, lineDecorations} = @props
[startRow, endRow] = renderedRowRange
visibleLines = editor.linesForScreenRows(startRow, endRow - 1)
@removeLineNodes(visibleLines)
@appendOrUpdateVisibleLineNodes(visibleLines, startRow)
@appendOrUpdateVisibleLineNodes(visibleLines, startRow, updateWidth)
removeLineNodes: (visibleLines=[]) ->
{mouseWheelScreenRow} = @props
@ -83,7 +83,7 @@ LinesComponent = React.createClass
delete @renderedDecorationsByLineId[lineId]
node.removeChild(lineNode)
appendOrUpdateVisibleLineNodes: (visibleLines, startRow) ->
appendOrUpdateVisibleLineNodes: (visibleLines, startRow, updateWidth) ->
{lineDecorations} = @props
newLines = null
@ -93,7 +93,7 @@ LinesComponent = React.createClass
screenRow = startRow + index
if @hasLineNode(line.id)
@updateLineNode(line, screenRow)
@updateLineNode(line, screenRow, updateWidth)
else
newLines ?= []
newLinesHTML ?= ""
@ -118,7 +118,7 @@ LinesComponent = React.createClass
@lineNodesByLineId.hasOwnProperty(lineId)
buildLineHTML: (line, screenRow) ->
{editor, mini, showIndentGuide, lineHeightInPixels, lineDecorations} = @props
{editor, mini, showIndentGuide, lineHeightInPixels, lineDecorations, lineWidth} = @props
{tokens, text, lineEnding, fold, isSoftWrapped, indentLevel} = line
classes = ''
@ -129,7 +129,7 @@ LinesComponent = React.createClass
classes += 'line'
top = screenRow * lineHeightInPixels
lineHTML = "<div class=\"#{classes}\" style=\"position: absolute; top: #{top}px; width: 100%;\" data-screen-row=\"#{screenRow}\">"
lineHTML = "<div class=\"#{classes}\" style=\"position: absolute; top: #{top}px; width: #{lineWidth}px;\" data-screen-row=\"#{screenRow}\">"
if text is ""
lineHTML += @buildEmptyLineInnerHTML(line)
@ -203,8 +203,8 @@ LinesComponent = React.createClass
scopeStack.push(scope)
"<span class=\"#{scope.replace(/\.+/g, ' ')}\">"
updateLineNode: (line, screenRow) ->
{editor, lineHeightInPixels, lineDecorations} = @props
updateLineNode: (line, screenRow, updateWidth) ->
{editor, lineHeightInPixels, lineDecorations, lineWidth} = @props
lineNode = @lineNodesByLineId[line.id]
decorations = lineDecorations[screenRow]
@ -219,6 +219,8 @@ LinesComponent = React.createClass
if editor.decorationMatchesType(decoration, 'line') and not _.deepContains(previousDecorations, decoration)
lineNode.classList.add(decoration.class)
lineNode.style.width = lineWidth + 'px' if updateWidth
unless @screenRowsByLineId[line.id] is screenRow
lineNode.style.top = screenRow * lineHeightInPixels + 'px'
lineNode.dataset.screenRow = screenRow