diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index 638ab6917..e0230fbb8 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -370,6 +370,24 @@ describe "TextEditorComponent", -> expect(leafNodes[0].classList.contains('trailing-whitespace')).toBe true expect(leafNodes[0].classList.contains('leading-whitespace')).toBe false + it "keeps rebuilding lines when continuous reflow is on", -> + wrapperNode.setContinuousReflow(true) + + oldLineNodes = componentNode.querySelectorAll(".line") + + advanceClock(10) + expect(nextAnimationFrame).toBe(noAnimationFrame) + + advanceClock(component.presenter.minimumReflowInterval - 10) + nextAnimationFrame() + + newLineNodes = componentNode.querySelectorAll(".line") + expect(oldLineNodes).not.toEqual(newLineNodes) + + wrapperNode.setContinuousReflow(false) + advanceClock(component.presenter.minimumReflowInterval) + expect(nextAnimationFrame).toBe(noAnimationFrame) + describe "when showInvisibles is enabled", -> invisibles = null @@ -807,6 +825,24 @@ describe "TextEditorComponent", -> expect(componentNode.querySelector('.gutter').style.display).toBe '' expect(component.lineNumberNodeForScreenRow(3)?).toBe true + it "keeps rebuilding line numbers when continuous reflow is on", -> + wrapperNode.setContinuousReflow(true) + + oldLineNodes = componentNode.querySelectorAll(".line-number") + + advanceClock(10) + expect(nextAnimationFrame).toBe(noAnimationFrame) + + advanceClock(component.presenter.minimumReflowInterval - 10) + nextAnimationFrame() + + newLineNodes = componentNode.querySelectorAll(".line-number") + expect(oldLineNodes).not.toEqual(newLineNodes) + + wrapperNode.setContinuousReflow(false) + advanceClock(component.presenter.minimumReflowInterval) + expect(nextAnimationFrame).toBe(noAnimationFrame) + describe "fold decorations", -> describe "rendering fold decorations", -> it "adds the foldable class to line numbers when the line is foldable", -> diff --git a/src/line-number-gutter-component.coffee b/src/line-number-gutter-component.coffee index f73068c30..b4a5bc168 100644 --- a/src/line-number-gutter-component.coffee +++ b/src/line-number-gutter-component.coffee @@ -64,6 +64,9 @@ class LineNumberGutterComponent extends TiledComponent buildComponentForTile: (id) -> new LineNumbersTileComponent({id, @domElementPool}) + shouldRecreateAllTilesOnUpdate: -> + @newState.continuousReflow + ### Section: Private Methods ### diff --git a/src/lines-component.coffee b/src/lines-component.coffee index b618563be..237f24958 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -32,7 +32,7 @@ class LinesComponent extends TiledComponent @domNode shouldRecreateAllTilesOnUpdate: -> - @oldState.indentGuidesVisible isnt @newState.indentGuidesVisible + @oldState.indentGuidesVisible isnt @newState.indentGuidesVisible or @newState.continuousReflow beforeUpdateSync: (state) -> if @newState.maxHeight isnt @oldState.maxHeight diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index 7ce212f34..36f56a877 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -819,6 +819,9 @@ class TextEditorComponent setInputEnabled: (@inputEnabled) -> @inputEnabled + setContinuousReflow: (continuousReflow) -> + @presenter.setContinuousReflow(continuousReflow) + updateParentViewFocusedClassIfNeeded: -> if @oldState.focused isnt @newState.focused @hostElement.classList.toggle('is-focused', @newState.focused) diff --git a/src/text-editor-element.coffee b/src/text-editor-element.coffee index fc027b0d8..55e4e8567 100644 --- a/src/text-editor-element.coffee +++ b/src/text-editor-element.coffee @@ -172,6 +172,12 @@ class TextEditorElement extends HTMLElement isUpdatedSynchronously: -> @updatedSynchronously + # Extended: Continuously reflows lines and line numbers. (Has performance overhead) + # + # `continuousReflow` A {Boolean} indicating whether to keep reflowing or not. + setContinuousReflow: (continuousReflow) -> + @component?.setContinuousReflow(continuousReflow) + # Extended: get the width of a character of text displayed in this element. # # Returns a {Number} of pixels. diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index cf31186a9..5e969864f 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -11,6 +11,7 @@ class TextEditorPresenter mouseWheelScreenRow: null scopedCharacterWidthsChangeCount: 0 overlayDimensions: {} + minimumReflowInterval: 200 constructor: (params) -> {@model, @autoHeight, @explicitHeight, @contentFrameWidth, @scrollTop, @scrollLeft, @boundingClientRect, @windowWidth, @windowHeight, @gutterWidth} = params @@ -35,6 +36,7 @@ class TextEditorPresenter @observeConfig() @buildState() @startBlinkingCursors() if @focused + @startReflowing() if @continuousReflow @updating = false destroy: -> @@ -72,6 +74,7 @@ class TextEditorPresenter @updateStartRow() @updateEndRow() @updateCommonGutterState() + @updateReflowState() @updateFocusedState() if @shouldUpdateFocusedState @updateHeightState() if @shouldUpdateHeightState @@ -254,6 +257,23 @@ class TextEditorPresenter @resetTrackedUpdates() + setContinuousReflow: (@continuousReflow) -> + if @continuousReflow + @startReflowing() + else + @stopReflowing() + + updateReflowState: -> + @state.content.continuousReflow = @continuousReflow + @lineNumberGutter.continuousReflow = @continuousReflow + + startReflowing: -> + @reflowingInterval = setInterval(@emitDidUpdateState.bind(this), @minimumReflowInterval) + + stopReflowing: -> + clearInterval(@reflowingInterval) + @reflowingInterval = null + updateFocusedState: -> @state.focused = @focused