Merge pull request #11852 from MikeInnes/overlay-scroll

Option for avoiding overlay movements
This commit is contained in:
Nathan Sobo
2016-12-12 10:51:07 -07:00
committed by GitHub
4 changed files with 64 additions and 18 deletions

View File

@@ -2522,13 +2522,13 @@ describe "TextEditorPresenter", ->
pixelPosition: {top: 1 * 10, left: 26 * 10 + gutterWidth - scrollLeft}
}
expectStateUpdate presenter, -> editor.insertText('a')
expectStateUpdate presenter, -> editor.insertText('abc', autoscroll: false)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 1 * 10, left: windowWidth - itemWidth}
}
expectStateUpdate presenter, -> editor.insertText('b')
expectStateUpdate presenter, -> editor.insertText('d', autoscroll: false)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 1 * 10, left: windowWidth - itemWidth}
@@ -2549,14 +2549,55 @@ describe "TextEditorPresenter", ->
}
expectStateUpdate presenter, ->
editor.insertNewline()
presenter.setScrollTop(scrollTop) # I'm fighting the editor
editor.insertNewline(autoscroll: false)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 6 * 10 - scrollTop - itemHeight, left: gutterWidth}
}
it "when avoidOverflow is false, does not move horizontally when overflowing the editor's scrollView horizontally", ->
scrollLeft = 20
marker = editor.markBufferPosition([0, 26], invalidate: 'never')
decoration = editor.decorateMarker(marker, {type: 'overlay', item, avoidOverflow: false})
presenter = buildPresenter({scrollLeft, windowWidth, windowHeight, contentFrameWidth, boundingClientRect, gutterWidth})
expectStateUpdate presenter, ->
presenter.setOverlayDimensions(decoration.id, itemWidth, itemHeight, contentMargin)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 1 * 10, left: 26 * 10 + gutterWidth - scrollLeft}
}
expectStateUpdate presenter, -> editor.insertText('a', autoscroll: false)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 1 * 10, left: 27 * 10 + gutterWidth - scrollLeft}
}
it "when avoidOverflow is false, does not flip vertically when overflowing the editor's scrollView vertically", ->
scrollTop = 10
marker = editor.markBufferPosition([5, 0], invalidate: 'never')
decoration = editor.decorateMarker(marker, {type: 'overlay', item, avoidOverflow: false})
presenter = buildPresenter({scrollTop, windowWidth, windowHeight, contentFrameWidth, boundingClientRect, gutterWidth})
expectStateUpdate presenter, ->
presenter.setOverlayDimensions(decoration.id, itemWidth, itemHeight, contentMargin)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 6 * 10 - scrollTop, left: gutterWidth}
}
expectStateUpdate presenter, ->
editor.insertNewline(autoscroll: false)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 7 * 10 - scrollTop, left: gutterWidth}
}
describe "when the overlay item has a margin", ->
beforeEach ->
itemWidth = 12 * 10

View File

@@ -366,7 +366,7 @@ class Selection extends Model
insertText: (text, options={}) ->
oldBufferRange = @getBufferRange()
wasReversed = @isReversed()
@clear()
@clear(options)
autoIndentFirstLine = false
precedingText = @editor.getTextInRange([[oldBufferRange.start.row, 0], oldBufferRange.start])
@@ -403,7 +403,7 @@ class Selection extends Model
else if options.autoDecreaseIndent and NonWhitespaceRegExp.test(text)
@editor.autoDecreaseIndentForBufferRow(newBufferRange.start.row)
@autoscroll() if @isLastSelection()
@autoscroll() if options.autoscroll ? @isLastSelection()
newBufferRange

View File

@@ -451,7 +451,7 @@ class TextEditorPresenter
for decoration in @model.getOverlayDecorations()
continue unless decoration.getMarker().isValid()
{item, position, class: klass} = decoration.getProperties()
{item, position, class: klass, avoidOverflow} = decoration.getProperties()
if position is 'tail'
screenPosition = decoration.getMarker().getTailScreenPosition()
else
@@ -466,15 +466,16 @@ class TextEditorPresenter
if overlayDimensions = @overlayDimensions[decoration.id]
{itemWidth, itemHeight, contentMargin} = overlayDimensions
rightDiff = left + itemWidth + contentMargin - @windowWidth
left -= rightDiff if rightDiff > 0
if avoidOverflow isnt false
rightDiff = left + itemWidth + contentMargin - @windowWidth
left -= rightDiff if rightDiff > 0
leftDiff = left + contentMargin
left -= leftDiff if leftDiff < 0
leftDiff = left + contentMargin
left -= leftDiff if leftDiff < 0
if top + itemHeight > @windowHeight and
top - (itemHeight + @lineHeight) >= 0
top -= itemHeight + @lineHeight
if top + itemHeight > @windowHeight and
top - (itemHeight + @lineHeight) >= 0
top -= itemHeight + @lineHeight
pixelPosition.top = top
pixelPosition.left = left

View File

@@ -1085,8 +1085,8 @@ class TextEditor extends Model
)
# Essential: For each selection, replace the selected text with a newline.
insertNewline: ->
@insertText('\n')
insertNewline: (options) ->
@insertText('\n', options)
# Essential: For each selection, if the selection is empty, delete the character
# following the cursor. Otherwise delete the selected text.
@@ -1749,10 +1749,14 @@ class TextEditor extends Model
# * `onlyNonEmpty` (optional) If `true`, the decoration will only be applied
# if the associated `DisplayMarker` is non-empty. Only applicable to the
# `gutter`, `line`, and `line-number` types.
# * `position` (optional) Only applicable to decorations of type `overlay` and `block`,
# controls where the view is positioned relative to the `TextEditorMarker`.
# * `position` (optional) Only applicable to decorations of type `overlay` and `block`.
# Controls where the view is positioned relative to the `TextEditorMarker`.
# Values can be `'head'` (the default) or `'tail'` for overlay decorations, and
# `'before'` (the default) or `'after'` for block decorations.
# * `avoidOverflow` (optional) Only applicable to decorations of type
# `overlay`. Determines whether the decoration adjusts its horizontal or
# vertical position to remain fully visible when it would otherwise
# overflow the editor. Defaults to `true`.
#
# Returns a {Decoration} object
decorateMarker: (marker, decorationParams) ->