Batch together line and character width measurement after font changes

This ensures we only perform a single update with the most up-to-date
information about line height, default character width, and specific
character widths. If this update causes more lines to be drawn we may
measure again, but not necessarily.
This commit is contained in:
Nathan Sobo
2014-06-02 17:52:10 +09:00
parent 4fd07a4cf3
commit 3aefa53b33
3 changed files with 34 additions and 32 deletions

View File

@@ -109,12 +109,12 @@ describe "EditorComponent", ->
it "updates the top position of lines when the font family changes", ->
# Can't find a font that changes the line height, but we think one might exist
linesComponent = component.refs.lines
spyOn(linesComponent, 'measureLineHeightInPixelsAndCharWidth').andCallFake -> editor.setLineHeightInPixels(10)
spyOn(linesComponent, 'measureLineHeightAndDefaultCharWidth').andCallFake -> editor.setLineHeightInPixels(10)
initialLineHeightInPixels = editor.getLineHeightInPixels()
component.setFontFamily('sans-serif')
expect(linesComponent.measureLineHeightInPixelsAndCharWidth).toHaveBeenCalled()
expect(linesComponent.measureLineHeightAndDefaultCharWidth).toHaveBeenCalled()
newLineHeightInPixels = editor.getLineHeightInPixels()
expect(newLineHeightInPixels).not.toBe initialLineHeightInPixels
expect(component.lineNodeForScreenRow(1).offsetTop).toBe 1 * newLineHeightInPixels
@@ -386,8 +386,9 @@ describe "EditorComponent", ->
it "updates cursor positions when the line height changes", ->
editor.setCursorBufferPosition([1, 10])
cursorNode = node.querySelector('.cursor')
component.setLineHeight(2)
cursorNode = node.querySelector('.cursor')
expect(cursorNode.style['-webkit-transform']).toBe "translate3d(#{10 * editor.getDefaultCharWidth()}px, #{editor.getLineHeightInPixels()}px, 0px)"
expect(cursorNode.style['-webkit-transform']).toBe "translate3d(#{10 * editor.getDefaultCharWidth()}px, #{editor.getLineHeightInPixels()}px, 0px)"
describe "selection rendering", ->

View File

@@ -35,7 +35,7 @@ EditorComponent = React.createClass
scrollViewMeasurementRequested: false
overflowChangedEventsPaused: false
overflowChangedWhilePaused: false
measureLineHeightInPixelsAndCharWidthWhenShown: false
measureLineHeightAndDefaultCharWidthWhenShown: false
render: ->
{focused, fontSize, lineHeight, fontFamily, showIndentGuide, showInvisibles, visible} = @state
@@ -140,17 +140,21 @@ EditorComponent = React.createClass
@observeConfig()
componentDidMount: ->
{editor} = @props
@observeEditor()
@listenForDOMEvents()
@listenForCommands()
@measureScrollbars()
@subscribe atom.themes, 'stylesheet-added stylsheet-removed', @onStylesheetsChanged
@subscribe scrollbarStyle.changes, @refreshScrollbars
@props.editor.setVisible(true)
@measureScrollView()
editor.setVisible(true)
@requestUpdate()
editor.batchUpdates =>
@measureLineHeightAndDefaultCharWidth()
@measureScrollView()
@measureScrollbars()
componentWillUnmount: ->
@unsubscribe()
@@ -163,11 +167,7 @@ EditorComponent = React.createClass
@pendingChanges.length = 0
@refreshingScrollbars = false
@measureScrollbars() if @measuringScrollbars
@measureLineHeightInPixelsAndCharWidthIfNeeded(prevState)
unless isEqualForProperties(prevState, @state, 'fontSize', 'fontFamily')
@refs.lines.clearScopedCharWidths()
@refs.lines.measureCharactersInNewLines()
@measureLineHeightAndCharWidthsIfNeeded(prevState)
@pauseOverflowChangedEvents()
@props.parentView.trigger 'editor:display-updated'
@@ -573,20 +573,24 @@ EditorComponent = React.createClass
clientWidth = scrollViewNode.clientWidth
editor.setWidth(clientWidth) if clientWidth > 0
measureLineHeightInPixelsAndCharWidthIfNeeded: (prevState) ->
unless isEqualForProperties(prevState, @state, 'lineHeight', 'fontSize', 'fontFamily')
if @state.visible
@measureLineHeightInPixelsAndCharWidth()
else
@measureLineHeightInPixelsAndCharWidthWhenShown = true
return
measureLineHeightAndCharWidthsIfNeeded: (prevState) ->
if not isEqualForProperties(prevState, @state, 'lineHeight', 'fontSize', 'fontFamily')
@props.editor.batchUpdates =>
if @state.visible
@measureLineHeightAndDefaultCharWidth()
else
@measureLineHeightAndDefaultCharWidthWhenShown = true
if @measureLineHeightInPixelsAndCharWidthWhenShown and @state.visible and not prevState.visible
@measureLineHeightInPixelsAndCharWidth()
unless isEqualForProperties(prevState, @state, 'fontSize', 'fontFamily')
@refs.lines.clearScopedCharWidths()
@refs.lines.measureCharactersInNewLines()
measureLineHeightInPixelsAndCharWidth: ->
@measureLineHeightInPixelsAndCharWidthWhenShown = false
@refs.lines.measureLineHeightInPixelsAndCharWidth()
else if @measureLineHeightAndDefaultCharWidthWhenShown and @state.visible and not prevState.visible
@measureLineHeightAndDefaultCharWidth()
measureLineHeightAndDefaultCharWidth: ->
@measureLineHeightAndDefaultCharWidthWhenShown = false
@refs.lines.measureLineHeightAndDefaultCharWidth()
measureScrollbars: ->
@measuringScrollbars = false

View File

@@ -30,9 +30,6 @@ LinesComponent = React.createClass
@screenRowsByLineId = {}
@lineIdsByScreenRow = {}
componentDidMount: ->
@measureLineHeightInPixelsAndCharWidth()
shouldComponentUpdate: (newProps) ->
return true unless isEqualForProperties(newProps, @props,
'renderedRowRange', 'selectionScreenRanges', 'lineHeightInPixels', 'defaultCharWidth',
@@ -200,8 +197,7 @@ LinesComponent = React.createClass
lineNodeForScreenRow: (screenRow) ->
@lineNodesByLineId[@lineIdsByScreenRow[screenRow]]
measureLineHeightInPixelsAndCharWidth: ->
@measureWhenShown = false
measureLineHeightAndDefaultCharWidth: ->
node = @getDOMNode()
node.appendChild(DummyLineNode)
lineHeightInPixels = DummyLineNode.getBoundingClientRect().height
@@ -209,8 +205,9 @@ LinesComponent = React.createClass
node.removeChild(DummyLineNode)
{editor} = @props
editor.setLineHeightInPixels(lineHeightInPixels)
editor.setDefaultCharWidth(charWidth)
editor.batchUpdates ->
editor.setLineHeightInPixels(lineHeightInPixels)
editor.setDefaultCharWidth(charWidth)
measureCharactersInNewLines: ->
[visibleStartRow, visibleEndRow] = @props.renderedRowRange