From 76241fb7790f353d438291ed656798eaf4d9f6b5 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 28 Jan 2015 16:55:49 -0700 Subject: [PATCH] Handle line and line number preservation in presenter The target of mousewheel events needs to be preserved when scrolling. It used to be dealt with in the view, but now we can do it in the presenter for a simpler view implementation. --- spec/text-editor-component-spec.coffee | 12 +++++------- src/gutter-component.coffee | 4 ++-- src/lines-component.coffee | 4 ++-- src/text-editor-component.coffee | 20 +++----------------- src/text-editor-presenter.coffee | 1 + 5 files changed, 13 insertions(+), 28 deletions(-) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index 17a37f064..6b1cb3953 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -2068,7 +2068,7 @@ describe "TextEditorComponent", -> componentNode.dispatchEvent(wheelEvent) nextAnimationFrame() - expect(component.mouseWheelScreenRow).toBe null + expect(component.presenter.getMouseWheelScreenRow()).toBe null it "clears the mouseWheelScreenRow after a delay even if the event does not cause scrolling", -> expect(editor.getScrollTop()).toBe 0 @@ -2077,13 +2077,12 @@ describe "TextEditorComponent", -> wheelEvent = new WheelEvent('mousewheel', wheelDeltaX: 0, wheelDeltaY: 10) Object.defineProperty(wheelEvent, 'target', get: -> lineNode) componentNode.dispatchEvent(wheelEvent) - expect(nextAnimationFrame).toBe noAnimationFrame expect(editor.getScrollTop()).toBe 0 - expect(component.mouseWheelScreenRow).toBe 0 - advanceClock(component.mouseWheelScreenRowClearDelay) - expect(component.mouseWheelScreenRow).toBe null + expect(component.presenter.getMouseWheelScreenRow()).toBe 0 + advanceClock(component.presenter.stoppedScrollingDelay) + expect(component.presenter.getMouseWheelScreenRow()).toBe null it "does not preserve the line if it is on screen", -> expect(componentNode.querySelectorAll('.line-number').length).toBe 14 # dummy line @@ -2094,9 +2093,8 @@ describe "TextEditorComponent", -> wheelEvent = new WheelEvent('mousewheel', wheelDeltaX: 0, wheelDeltaY: 100) # goes nowhere, we're already at scrollTop 0 Object.defineProperty(wheelEvent, 'target', get: -> lineNode) componentNode.dispatchEvent(wheelEvent) - expect(nextAnimationFrame).toBe noAnimationFrame - expect(component.mouseWheelScreenRow).toBe 0 + expect(component.presenter.getMouseWheelScreenRow()).toBe 0 editor.insertText("hello") expect(componentNode.querySelectorAll('.line-number').length).toBe 14 # dummy line expect(componentNode.querySelectorAll('.line').length).toBe 13 diff --git a/src/gutter-component.coffee b/src/gutter-component.coffee index f8538d1e4..26469065b 100644 --- a/src/gutter-component.coffee +++ b/src/gutter-component.coffee @@ -69,7 +69,7 @@ GutterComponent = React.createClass @dummyLineNumberNode.innerHTML = @buildLineNumberInnerHTML(0, false) updateLineNumbers: -> - {presenter, mouseWheelScreenRow} = @props + {presenter} = @props @oldState ?= {lineNumbers: {}} newState = presenter.state.gutter newLineNumberIds = null @@ -96,7 +96,7 @@ GutterComponent = React.createClass node.appendChild(lineNumberNode) for id, lineNumberState of @oldState.lineNumbers - unless newState.lineNumbers.hasOwnProperty(id) or lineNumberState.screenRow is mouseWheelScreenRow + unless newState.lineNumbers.hasOwnProperty(id) @lineNumberNodesById[id].remove() delete @lineNumberNodesById[id] delete @oldState.lineNumbers[id] diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 02e1a2470..6e1898cdd 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -92,10 +92,10 @@ LinesComponent = React.createClass delete @oldState.content.lines[id] updateLineNodes: -> - {presenter, mouseWheelScreenRow} = @props + {presenter} = @props for id of @oldState.content.lines - unless @newState.content.lines.hasOwnProperty(id) or mouseWheelScreenRow is @screenRowsByLineId[id] + unless @newState.content.lines.hasOwnProperty(id) @removeLineNode(id) newLineIds = null diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index 690379667..876716593 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -31,8 +31,6 @@ TextEditorComponent = React.createClass updateRequestedWhilePaused: false cursorMoved: false selectionChanged: false - mouseWheelScreenRow: null - mouseWheelScreenRowClearDelay: 150 scrollSensitivity: 0.4 heightAndWidthMeasurementRequested: false inputEnabled: true @@ -66,8 +64,6 @@ TextEditorComponent = React.createClass horizontallyScrollable = editor.horizontallyScrollable() hiddenInputStyle = @getHiddenInputPosition() hiddenInputStyle.WebkitTransform = 'translateZ(0)' if @useHardwareAcceleration - if @mouseWheelScreenRow? and not (renderedStartRow <= @mouseWheelScreenRow < renderedEndRow) - mouseWheelScreenRow = @mouseWheelScreenRow style.height = scrollHeight if @autoHeight @@ -82,7 +78,7 @@ TextEditorComponent = React.createClass if @gutterVisible GutterComponent { ref: 'gutter', onMouseDown: @onGutterMouseDown, - @presenter, editor, mouseWheelScreenRow, @useHardwareAcceleration + @presenter, editor, @useHardwareAcceleration } div ref: 'scrollView', className: 'scroll-view', @@ -92,8 +88,7 @@ TextEditorComponent = React.createClass style: hiddenInputStyle LinesComponent { - ref: 'lines', @presenter, editor, hostElement, @useHardwareAcceleration, useShadowDOM, - mouseWheelScreenRow, visible + ref: 'lines', @presenter, editor, hostElement, @useHardwareAcceleration, useShadowDOM, visible } ScrollbarComponent @@ -433,9 +428,7 @@ TextEditorComponent = React.createClass event.preventDefault() unless previousScrollLeft is editor.getScrollLeft() else # Scrolling vertically - @mouseWheelScreenRow = @screenRowForNode(event.target) - @clearMouseWheelScreenRowAfterDelay ?= debounce(@clearMouseWheelScreenRow, @mouseWheelScreenRowClearDelay) - @clearMouseWheelScreenRowAfterDelay() + @presenter.setMouseWheelScreenRow(@screenRowForNode(event.target)) previousScrollTop = editor.getScrollTop() editor.setScrollTop(previousScrollTop - Math.round(wheelDeltaY * @scrollSensitivity)) event.preventDefault() unless previousScrollTop is editor.getScrollTop() @@ -846,13 +839,6 @@ TextEditorComponent = React.createClass horizontalNode.style.display = originalHorizontalDisplayValue cornerNode.style.display = originalCornerDisplayValue - clearMouseWheelScreenRow: -> - if @mouseWheelScreenRow? - @mouseWheelScreenRow = null - @requestUpdate() - - clearMouseWheelScreenRowAfterDelay: null # created lazily - consolidateSelections: (e) -> e.abortKeyBinding() unless @props.editor.consolidateSelections() diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index e1c783021..3530e4f81 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -7,6 +7,7 @@ class TextEditorPresenter toggleCursorBlinkHandle: null startBlinkingCursorsAfterDelay: null stoppedScrollingTimeoutId: null + mouseWheelScreenRow: null constructor: (params) -> {@model, @clientHeight, @clientWidth, @scrollTop, @scrollLeft} = params