From 99c437ccecff469d2fc4ba70ff3ff9a0f694f9e6 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 26 Mar 2015 16:48:21 -0600 Subject: [PATCH] Allow autoscroll override option in cursor/selection methods Signed-off-by: Max Brunsfeld --- spec/text-editor-component-spec.coffee | 6 +++--- spec/text-editor-presenter-spec.coffee | 12 ++++++------ spec/text-editor-spec.coffee | 24 ++++++++++++++++++++++++ src/cursor.coffee | 16 +++++++++++----- src/selection.coffee | 24 +++++++++++++++++++----- src/text-editor.coffee | 19 ++++++++++++++----- 6 files changed, 77 insertions(+), 24 deletions(-) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index 20ddcdcab..135e551a3 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -693,7 +693,7 @@ describe "TextEditorComponent", -> describe "cursor rendering", -> it "renders the currently visible cursors", -> cursor1 = editor.getLastCursor() - cursor1.setScreenPosition([0, 5]) + cursor1.setScreenPosition([0, 5], autoscroll: false) wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px' wrapperNode.style.width = 20 * lineHeightInPixels + 'px' @@ -706,8 +706,8 @@ describe "TextEditorComponent", -> expect(cursorNodes[0].offsetWidth).toBe charWidth expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{5 * charWidth}px, #{0 * lineHeightInPixels}px)" - cursor2 = editor.addCursorAtScreenPosition([8, 11]) - cursor3 = editor.addCursorAtScreenPosition([4, 10]) + cursor2 = editor.addCursorAtScreenPosition([8, 11], autoscroll: false) + cursor3 = editor.addCursorAtScreenPosition([4, 10], autoscroll: false) nextAnimationFrame() cursorNodes = componentNode.querySelectorAll('.cursor') diff --git a/spec/text-editor-presenter-spec.coffee b/spec/text-editor-presenter-spec.coffee index 0cf0c7e53..b62391db8 100644 --- a/spec/text-editor-presenter-spec.coffee +++ b/spec/text-editor-presenter-spec.coffee @@ -1417,33 +1417,33 @@ describe "TextEditorPresenter", -> expect(stateForSelection(presenter, 1)).toBeUndefined() # moving into view - expectStateUpdate presenter, -> editor.getSelections()[1].setBufferRange([[2, 4], [2, 6]]) + expectStateUpdate presenter, -> editor.getSelections()[1].setBufferRange([[2, 4], [2, 6]], autoscroll: false) expectValues stateForSelection(presenter, 1), { regions: [{top: 2 * 10, left: 4 * 10, width: 2 * 10, height: 10}] } # becoming empty - expectStateUpdate presenter, -> editor.getSelections()[1].clear() + expectStateUpdate presenter, -> editor.getSelections()[1].clear(autoscroll: false) expect(stateForSelection(presenter, 1)).toBeUndefined() # becoming non-empty - expectStateUpdate presenter, -> editor.getSelections()[1].setBufferRange([[2, 4], [2, 6]]) + expectStateUpdate presenter, -> editor.getSelections()[1].setBufferRange([[2, 4], [2, 6]], autoscroll: false) expectValues stateForSelection(presenter, 1), { regions: [{top: 2 * 10, left: 4 * 10, width: 2 * 10, height: 10}] } # moving out of view - expectStateUpdate presenter, -> editor.getSelections()[1].setBufferRange([[3, 4], [3, 6]]) + expectStateUpdate presenter, -> editor.getSelections()[1].setBufferRange([[3, 4], [3, 6]], autoscroll: false) expect(stateForSelection(presenter, 1)).toBeUndefined() # adding - expectStateUpdate presenter, -> editor.addSelectionForBufferRange([[1, 4], [1, 6]]) + expectStateUpdate presenter, -> editor.addSelectionForBufferRange([[1, 4], [1, 6]], autoscroll: false) expectValues stateForSelection(presenter, 2), { regions: [{top: 1 * 10, left: 4 * 10, width: 2 * 10, height: 10}] } # moving added selection - expectStateUpdate presenter, -> editor.getSelections()[2].setBufferRange([[1, 4], [1, 8]]) + expectStateUpdate presenter, -> editor.getSelections()[2].setBufferRange([[1, 4], [1, 8]], autoscroll: false) expectValues stateForSelection(presenter, 2), { regions: [{top: 1 * 10, left: 4 * 10, width: 4 * 10, height: 10}] } diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index afebf591d..49b75bafd 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -993,6 +993,30 @@ describe "TextEditor", -> editor.undo() expect(editor.getScrollTop()).toBe 0 + it "honors the autoscroll option on cursor and selection manipulation methods", -> + expect(editor.getScrollTop()).toBe 0 + editor.addCursorAtScreenPosition([11, 11], autoscroll: false) + editor.addCursorAtBufferPosition([11, 11], autoscroll: false) + editor.setCursorScreenPosition([11, 11], autoscroll: false) + editor.setCursorBufferPosition([11, 11], autoscroll: false) + editor.addSelectionForBufferRange([[11, 11], [11, 11]], autoscroll: false) + editor.addSelectionForScreenRange([[11, 11], [11, 12]], autoscroll: false) + editor.setSelectedBufferRange([[11, 0], [11, 1]], autoscroll: false) + editor.setSelectedScreenRange([[11, 0], [11, 6]], autoscroll: false) + editor.clearSelections(autoscroll: false) + expect(editor.getScrollTop()).toBe 0 + + editor.addSelectionForScreenRange([[0, 0], [0, 4]]) + + editor.getCursors()[0].setScreenPosition([11, 11], autoscroll: true) + expect(editor.getScrollTop()).toBeGreaterThan 0 + editor.getCursors()[0].setBufferPosition([0, 0], autoscroll: true) + expect(editor.getScrollTop()).toBe 0 + editor.getSelections()[0].setScreenRange([[11, 0], [11, 4]], autoscroll: true) + expect(editor.getScrollTop()).toBeGreaterThan 0 + editor.getSelections()[0].setBufferRange([[0, 0], [0, 4]], autoscroll: true) + expect(editor.getScrollTop()).toBe 0 + describe '.logCursorScope()', -> beforeEach -> spyOn(atom.notifications, 'addInfo') diff --git a/src/cursor.coffee b/src/cursor.coffee index d0602a2f4..2e67ab43b 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -122,8 +122,9 @@ class Cursor extends Model # # * `bufferPosition` {Array} of two numbers: the buffer row, and the buffer column. # * `options` (optional) {Object} with the following keys: - # * `autoscroll` A Boolean which, if `true`, scrolls the {TextEditor} to wherever - # the cursor moves to. + # * `autoscroll` {Boolean} indicating whether to autoscroll to the new + # position. Defaults to `true` if this is the most recently added cursor, + # `false` otherwise. setBufferPosition: (bufferPosition, options={}) -> @changePosition options, => @marker.setHeadBufferPosition(bufferPosition, options) @@ -648,8 +649,12 @@ class Cursor extends Model changePosition: (options, fn) -> @clearSelection() - fn() - @autoscroll() if options.autoscroll + @editor.suppressAutoscroll = true if options.autoscroll is false + try + fn() + finally + @editor.suppressAutoscroll = false if options?.autoscroll is false + @autoscroll() if options.autoscroll is true getPixelRect: -> @editor.pixelRectForScreenRange(@getScreenRange()) @@ -659,7 +664,8 @@ class Cursor extends Model new Range(new Point(row, column), new Point(row, column + 1)) autoscroll: (options) -> - @editor.scrollToScreenRange(@getScreenRange(), options) + unless @editor.suppressAutoscroll + @editor.scrollToScreenRange(@getScreenRange(), options) getBeginningOfNextParagraphBufferPosition: -> start = @getBufferPosition() diff --git a/src/selection.coffee b/src/selection.coffee index df0e4a5d1..4987708eb 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -95,8 +95,11 @@ class Selection extends Model # # * `screenRange` The new {Range} to select. # * `options` (optional) {Object} with the keys: - # * `preserveFolds` if `true`, the fold settings are preserved after the selection moves. - # * `autoscroll` if `true`, the {TextEditor} scrolls to the new selection. + # * `preserveFolds` if `true`, the fold settings are preserved after the + # selection moves. + # * `autoscroll` {Boolean} indicating whether to autoscroll to the new + # range. Defaults to `true` if this is the most recently added selection, + # `false` otherwise. setBufferRange: (bufferRange, options={}) -> bufferRange = Range.fromObject(bufferRange) options.reversed ?= @isReversed() @@ -104,8 +107,10 @@ class Selection extends Model @modifySelection => needsFlash = options.flash delete options.flash if options.flash? + @editor.suppressAutoscroll = true if options.autoscroll is false @marker.setBufferRange(bufferRange, options) - @autoscroll() if options.autoscroll + @editor.suppressAutoscroll = false if options.autoscroll is false + @autoscroll() if options?.autoscroll is true @decoration.flash('flash', @editor.selectionFlashDuration) if needsFlash # Public: Returns the starting and ending buffer rows the selection is @@ -181,9 +186,17 @@ class Selection extends Model ### # Public: Clears the selection, moving the marker to the head. - clear: -> + # + # * `options` (optional) {Object} with the following keys: + # * `autoscroll` {Boolean} indicating whether to autoscroll to the new + # range. Defaults to `true` if this is the most recently added selection, + # `false` otherwise. + clear: (options) -> + @editor.suppressAutoscroll = true if options?.autoscroll is false @marker.setProperties(goalScreenRange: null) @marker.clearTail() unless @retainSelection + @editor.suppressAutoscroll = false if options?.autoscroll is false + @autoscroll() if options?.autoscroll is true @finalize() # Public: Selects the text from the current cursor position to a given screen @@ -757,7 +770,8 @@ class Selection extends Model @linewise = false autoscroll: -> - @editor.scrollToScreenRange(@getScreenRange(), reversed: @isReversed()) + unless @editor.suppressAutoscroll + @editor.scrollToScreenRange(@getScreenRange(), reversed: @isReversed()) clearAutoscroll: -> diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 820737834..beaf4aaac 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -69,6 +69,7 @@ class TextEditor extends Model suppressSelectionMerging: false updateBatchDepth: 0 selectionFlashDuration: 500 + suppressAutoscroll: false @delegatesMethods 'suggestedIndentForBufferRow', 'autoIndentBufferRow', 'autoIndentBufferRows', 'autoDecreaseIndentForBufferRow', 'toggleLineCommentForBufferRow', 'toggleLineCommentsForBufferRows', @@ -1606,8 +1607,10 @@ class TextEditor extends Model # * `bufferPosition` A {Point} or {Array} of `[row, column]` # # Returns a {Cursor}. - addCursorAtBufferPosition: (bufferPosition) -> + addCursorAtBufferPosition: (bufferPosition, options) -> + @suppressAutoscroll = true if options?.autoscroll is false @markBufferPosition(bufferPosition, @getSelectionMarkerAttributes()) + @suppressAutoscroll = false if options?.autoscroll is false @getLastSelection().cursor # Essential: Add a cursor at the position in screen coordinates. @@ -1615,8 +1618,10 @@ class TextEditor extends Model # * `screenPosition` A {Point} or {Array} of `[row, column]` # # Returns a {Cursor}. - addCursorAtScreenPosition: (screenPosition) -> + addCursorAtScreenPosition: (screenPosition, options) -> + @suppressAutoscroll = true if options?.autoscroll is false @markScreenPosition(screenPosition, @getSelectionMarkerAttributes()) + @suppressAutoscroll = false if options?.autoscroll is false @getLastSelection().cursor # Essential: Returns {Boolean} indicating whether or not there are multiple cursors. @@ -1946,7 +1951,9 @@ class TextEditor extends Model # # Returns the added {Selection}. addSelectionForBufferRange: (bufferRange, options={}) -> + @suppressAutoscroll = true if options.autoscroll is false @markBufferRange(bufferRange, _.defaults(@getSelectionMarkerAttributes(), options)) + @suppressAutoscroll = false if options.autoscroll is false @getLastSelection() # Essential: Add a selection for the given range in screen coordinates. @@ -1958,7 +1965,9 @@ class TextEditor extends Model # # Returns the added {Selection}. addSelectionForScreenRange: (screenRange, options={}) -> + @suppressAutoscroll = true if options.autoscroll is false @markScreenRange(screenRange, _.defaults(@getSelectionMarkerAttributes(), options)) + @suppressAutoscroll = false if options.autoscroll is false @getLastSelection() # Essential: Select from the current cursor position to the given position in @@ -2272,7 +2281,7 @@ class TextEditor extends Model selection.autoscroll() return selection else - selection.autoscroll() + selection.autoscroll() unless options.autoscroll is false @emit 'selection-added', selection @emitter.emit 'did-add-selection', selection selection @@ -2285,9 +2294,9 @@ class TextEditor extends Model # Reduce one or more selections to a single empty selection based on the most # recently added cursor. - clearSelections: -> + clearSelections: (options) -> @consolidateSelections() - @getLastSelection().clear() + @getLastSelection().clear(options) # Reduce multiple selections to the most recently added selection. consolidateSelections: ->