From cef9ce6ca7191cd8927357d2c4c06d89feb1e53d Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 13 Nov 2012 17:01:12 -0700 Subject: [PATCH] Add `needsUpdate` and `needsAutoscroll` properties to cursor views Then in the editor, we update and autoscroll only the views that need it. Autoscrolling is suppressed when resetting the display so that we honor the scroll positions of the active EditSession. --- spec/app/editor-spec.coffee | 6 ++--- src/app/cursor-view.coffee | 44 +++++++++++++++++++++---------------- src/app/editor.coffee | 29 ++++++++++++++---------- 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index 1ccfab796..3c048d890 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -659,13 +659,11 @@ describe "Editor", -> it "places an additional cursor", -> editor.attachToDom() setEditorHeightInLines(editor, 5) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 0]) + editor.setCursorBufferPosition([3, 0]) editor.scrollTop(editor.lineHeight * 6) - spyOn(editor, "scrollTo").andCallThrough() - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [6, 0], metaKey: true) - expect(editor.scrollTo.callCount).toBe 1 + expect(editor.scrollTop()).toBe editor.lineHeight * (6 - editor.vScrollMargin) [cursor1, cursor2] = editor.getCursorViews() expect(cursor1.position()).toEqual(top: 3 * editor.lineHeight, left: 0) diff --git a/src/app/cursor-view.coffee b/src/app/cursor-view.coffee index 24e77c6a6..1c1a4fcfa 100644 --- a/src/app/cursor-view.coffee +++ b/src/app/cursor-view.coffee @@ -12,15 +12,27 @@ class CursorView extends View editor: null visible: true - initialize: (@cursor, @editor, options={}) -> + needsUpdate: true + needsAutoscroll: true + needsRemoval: false + + initialize: (@cursor, @editor) -> @cursor.on 'change-screen-position.cursor-view', (screenPosition, { bufferChange, autoscroll }) => - @updateDisplay({autoscroll}) + @needsUpdate = true + @needsAutoscroll = (autoscroll ? true) and @cursor?.isLastCursor() + @editor.updateDisplay() + + # TODO: Move idle/active to the cursor model @removeIdleClassTemporarily() unless bufferChange @trigger 'cursor-move', {bufferChange} - @cursor.on 'change-visibility.cursor-view', (visible) => @setVisible(visible) + @cursor.on 'change-visibility.cursor-view', (visible) => + @needsUpdate = true + @needsAutoscroll = visible and @cursor.isLastCursor() + @editor.updateDisplay() + @cursor.on 'destroy.cursor-view', => - @destroyed = true + @needsRemoval = true @editor.updateDisplay() remove: -> @@ -28,29 +40,23 @@ class CursorView extends View @cursor.off('.cursor-view') super - updateDisplay: (options={}) -> - autoscroll = options.autoscroll ? true + updateDisplay: -> screenPosition = @getScreenPosition() pixelPosition = @getPixelPosition() - @css(pixelPosition) - @autoscroll() if @cursor.isLastCursor() and autoscroll + + unless _.isEqual(@lastPixelPosition, pixelPosition) + changedPosition = true + @css(pixelPosition) + @setVisible(@cursor.isVisible() and not @editor.isFoldedAtScreenRow(screenPosition.row)) getPixelPosition: -> @editor.pixelPositionForScreenPosition(@getScreenPosition()) - autoscroll: -> - @editor.scrollTo(@getPixelPosition()) - setVisible: (visible) -> - return if visible == @visible - @visible = visible - - if @visible - @show() - @autoscroll() - else - @hide() + unless @visible == visible + @visible = visible + @toggle(@visible) getBufferPosition: -> @cursor.getBufferPosition() diff --git a/src/app/editor.coffee b/src/app/editor.coffee index f7a65183e..93489e132 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -458,15 +458,15 @@ class Editor extends View getOpenBufferPaths: -> editSession.buffer.getPath() for editSession in @editSessions when editSession.buffer.getPath()? - scrollTop: (scrollTop, options) -> + scrollTop: (scrollTop, options={}) -> return @cachedScrollTop or 0 unless scrollTop? - + updateDisplay = options.updateDisplay ? true maxScrollTop = @verticalScrollbar.prop('scrollHeight') - @verticalScrollbar.height() scrollTop = Math.floor(Math.max(0, Math.min(maxScrollTop, scrollTop))) return if scrollTop == @cachedScrollTop @cachedScrollTop = scrollTop - @updateDisplay(autoscroll: false) if @attached + @updateDisplay(autoscroll: false) if @attached and updateDisplay @renderedLines.css('top', -scrollTop) @underlayer.css('top', -scrollTop) @@ -531,7 +531,7 @@ class Editor extends View element.removeClass('selected') setScrollPositionFromActiveEditSession: -> - @scrollTop(@activeEditSession.scrollTop ? 0) + @scrollTop(@activeEditSession.scrollTop ? 0, updateDisplay: false) @scrollView.scrollLeft(@activeEditSession.scrollLeft ? 0) saveActiveEditSession: -> @@ -655,17 +655,17 @@ class Editor extends View removeCursorView: (cursorView) -> _.remove(@cursorViews, cursorView) - updateCursorViews: (options)-> + updateCursorViews: -> if @newCursors.length > 0 @addCursorView(cursor) for cursor in @newCursors @syncCursorAnimations() @newCursors = [] for cursorView in @getCursorViews() - if cursorView.destroyed + if cursorView.needsRemoval cursorView.remove() - else - cursorView.updateDisplay(options) + else if cursorView.needsUpdate + cursorView.updateDisplay() updateSelectionViews: -> if @newSelections.length > 0 @@ -763,15 +763,20 @@ class Editor extends View @newCursors = @activeEditSession.getCursors() @newSelections = @activeEditSession.getSelections() - @updateDisplay(autoscroll: false) + @updateDisplay(suppressAutoScroll: true) - updateDisplay: (options) -> + updateDisplay: (options={}) -> return unless @attached - - @updateCursorViews(options) + @updateCursorViews() @updateSelectionViews() + @autoscroll(options) @updateRenderedLines() + autoscroll: (options={}) -> + for cursorView in @getCursorViews() when cursorView.needsAutoscroll + @scrollTo(cursorView.getPixelPosition()) unless options.suppressAutoScroll + cursorView.needsAutoscroll = false + updateRenderedLines: -> firstVisibleScreenRow = @getFirstVisibleScreenRow() lastVisibleScreenRow = @getLastVisibleScreenRow()