Make presenter respond to external changes to model's first visible screen row

This commit is contained in:
Max Brunsfeld
2015-11-09 10:13:09 -08:00
parent b58752da38
commit 48cc5e713e
3 changed files with 98 additions and 6 deletions

View File

@@ -4784,6 +4784,71 @@ describe "TextEditor", ->
editor.selectPageUp()
expect(editor.getSelectedBufferRanges()).toEqual [[[0, 0], [12, 2]]]
describe "::setFirstVisibleScreenRow() and ::getFirstVisibleScreenRow()", ->
beforeEach ->
line = Array(9).join('0123456789')
editor.setText([1..100].map(-> line).join('\n'))
expect(editor.getLineCount()).toBe 100
expect(editor.lineTextForBufferRow(0).length).toBe 80
describe "when the editor doesn't have a height and lineHeightInPixels", ->
it "does not affect the editor's visible row range", ->
expect(editor.getVisibleRowRange()).toBeNull()
editor.setFirstVisibleScreenRow(1)
expect(editor.getFirstVisibleScreenRow()).toEqual 1
editor.setFirstVisibleScreenRow(3)
expect(editor.getFirstVisibleScreenRow()).toEqual 3
expect(editor.getVisibleRowRange()).toBeNull()
describe "when the editor has a height and lineHeightInPixels", ->
beforeEach ->
atom.config.set('editor.scrollPastEnd', true)
editor.setHeight(100, true)
editor.setLineHeightInPixels(10)
it "updates the editor's visible row range", ->
editor.setFirstVisibleScreenRow(2)
expect(editor.getFirstVisibleScreenRow()).toEqual 2
expect(editor.getVisibleRowRange()).toEqual [2, 12]
it "notifies ::onDidChangeFirstVisibleScreenRow observers", ->
changeCount = 0
editor.onDidChangeFirstVisibleScreenRow -> changeCount++
editor.setFirstVisibleScreenRow(2)
expect(changeCount).toBe 1
editor.setFirstVisibleScreenRow(2)
expect(changeCount).toBe 1
editor.setFirstVisibleScreenRow(3)
expect(changeCount).toBe 2
it "ensures that the top row is less than the buffer's line count", ->
editor.setFirstVisibleScreenRow(102)
expect(editor.getFirstVisibleScreenRow()).toEqual 99
expect(editor.getVisibleRowRange()).toEqual [99, 99]
it "ensures that the left column is less than the length of the longest screen line", ->
editor.setFirstVisibleScreenRow(10)
expect(editor.getFirstVisibleScreenRow()).toEqual 10
editor.setText("\n\n\n")
editor.setFirstVisibleScreenRow(10)
expect(editor.getFirstVisibleScreenRow()).toEqual 3
describe "when the 'editor.scrollPastEnd' option is set to false", ->
it "ensures that the bottom row is less than the buffer's line count", ->
atom.config.set('editor.scrollPastEnd', false)
editor.setFirstVisibleScreenRow(95)
expect(editor.getFirstVisibleScreenRow()).toEqual 89
expect(editor.getVisibleRowRange()).toEqual [89, 99]
describe '.get/setPlaceholderText()', ->
it 'can be created with placeholderText', ->
newEditor = atom.workspace.buildTextEditor(

View File

@@ -213,6 +213,7 @@ class TextEditorPresenter
@disposables.add @model.onDidAddDecoration(@didAddDecoration.bind(this))
@disposables.add @model.onDidAddCursor(@didAddCursor.bind(this))
@disposables.add @model.onDidRequestAutoscroll(@requestAutoscroll.bind(this))
@disposables.add @model.onDidChangeFirstVisibleScreenRow(@didChangeFirstVisibleScreenRow.bind(this))
@observeDecoration(decoration) for decoration in @model.getDecorations()
@observeCursor(cursor) for cursor in @model.getCursors()
@disposables.add @model.onDidAddGutter(@didAddGutter.bind(this))
@@ -776,7 +777,7 @@ class TextEditorPresenter
if scrollTop isnt @realScrollTop and not Number.isNaN(scrollTop)
@realScrollTop = scrollTop
@scrollTop = Math.round(scrollTop)
@model.setFirstVisibleScreenRow(Math.round(@scrollTop / @lineHeight))
@model.setFirstVisibleScreenRow(Math.round(@scrollTop / @lineHeight), true)
@updateStartRow()
@updateEndRow()
@@ -1539,6 +1540,9 @@ class TextEditorPresenter
@emitDidUpdateState()
didChangeFirstVisibleScreenRow: (screenRow) ->
@updateScrollTop(screenRow * @lineHeight)
getVerticalScrollMarginInPixels: ->
Math.round(@model.getVerticalScrollMargin() * @lineHeight)

View File

@@ -448,6 +448,9 @@ class TextEditor extends Model
onDidChangeCharacterWidths: (callback) ->
@displayBuffer.onDidChangeCharacterWidths(callback)
onDidChangeFirstVisibleScreenRow: (callback, fromView) ->
@emitter.on 'did-change-first-visible-screen-row', callback
onDidChangeScrollTop: (callback) ->
Grim.deprecate("This is now a view method. Call TextEditorElement::onDidChangeScrollTop instead.")
@@ -3088,13 +3091,27 @@ class TextEditor extends Model
Grim.deprecate("This is now a view method. Call TextEditorElement::getWidth instead.")
@displayBuffer.getWidth()
setFirstVisibleScreenRow: (@firstVisibleScreenRow) ->
# Experimental: Scroll the editor such that the given screen row is at the
# top of the visible area.
setFirstVisibleScreenRow: (screenRow, fromView) ->
unless fromView
maxScreenRow = @getLineCount() - 1
unless @config.get('editor.scrollPastEnd')
height = @displayBuffer.getHeight()
lineHeightInPixels = @displayBuffer.getLineHeightInPixels()
if height? and lineHeightInPixels?
maxScreenRow -= Math.floor(height / lineHeightInPixels)
screenRow = Math.min(screenRow, maxScreenRow)
unless screenRow is @firstVisibleScreenRow
@emitter.emit 'did-change-first-visible-screen-row', screenRow unless fromView
@firstVisibleScreenRow = screenRow
getFirstVisibleScreenRow: -> @firstVisibleScreenRow
setFirstVisibleScreenColumn: (@firstVisibleScreenColumn) ->
getFirstVisibleScreenColumn: -> @firstVisibleScreenColumn
getScrollTop: ->
Grim.deprecate("This is now a view method. Call TextEditorElement::getScrollTop instead.")
@@ -3151,9 +3168,15 @@ class TextEditor extends Model
@viewRegistry.getView(this).getMaxScrollTop()
getVisibleRowRange: ->
Grim.deprecate("This is now a view method. Call TextEditorElement::getVisibleRowRange instead.")
@viewRegistry.getView(this).getVisibleRowRange()
height = @displayBuffer.getHeight()
lineHeightInPixels = @displayBuffer.getLineHeightInPixels()
if height? and lineHeightInPixels?
[
@firstVisibleScreenRow,
Math.min(@firstVisibleScreenRow + Math.floor(height / lineHeightInPixels), @getLineCount() - 1)
]
else
null
intersectsVisibleRowRange: (startRow, endRow) ->
Grim.deprecate("This is now a view method. Call TextEditorElement::intersectsVisibleRowRange instead.")