Update visible lines when scrolling up

This commit is contained in:
Corey Johnson & Nathan Sobo
2012-05-10 16:11:05 -06:00
parent 43ac7edf0f
commit 02da32d372
2 changed files with 70 additions and 55 deletions

View File

@@ -391,55 +391,68 @@ describe "Editor", ->
otherEditor.simulateDomAttachment()
expect(otherEditor.setMaxLineLength).toHaveBeenCalled()
describe "when some lines at the end of the buffer are not visible on screen when the editor is attached", ->
beforeEach ->
editor.attachToDom(heightInLines: 5.5)
it "only renders the visible lines, giving the final line a margin-bottom to account for the missing lines", ->
it "only renders the visible lines, setting the padding-bottom of the lines element to account for the missing lines", ->
expect(editor.lines.find('.line').length).toBe 6
expectedMarginBottom = (buffer.numLines() - 6) * editor.lineHeight
expect(editor.lines.find('.line:last').css('margin-bottom')).toBe "#{expectedMarginBottom}px"
expectedPaddingBottom = (buffer.numLines() - 6) * editor.lineHeight
expect(editor.lines.css('padding-bottom')).toBe "#{expectedPaddingBottom}px"
it "when the lines are scrolled down, removes lines that become invisible and builds lines that become visisble", ->
editor.scroller.scrollTop(editor.lineHeight * 2.5)
editor.scroller.trigger 'scroll'
describe "when the scroller element is scrolled", ->
describe "whes scrolling less than the editor's height", ->
it "removes lines that become invisible and builds lines that become visisble", ->
editor.scroller.scrollTop(editor.lineHeight * 2.5)
editor.scroller.trigger 'scroll'
expect(editor.lines.find('.line').length).toBe 6
expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(2)
expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(7)
expect(editor.lines.find('.line').length).toBe 6
expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(2)
expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(7)
editor.scroller.scrollTop(editor.lineHeight * 3.5)
editor.scroller.trigger 'scroll'
expect(editor.lines.find('.line').length).toBe 6
expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(3)
expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(8)
editor.scroller.scrollTop(editor.lineHeight * 3.5)
editor.scroller.trigger 'scroll'
editor.scroller.scrollTop(editor.lineHeight * 2.5)
editor.scroller.trigger 'scroll'
expect(editor.lines.find('.line').length).toBe 6
expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(2)
expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(7)
expect(editor.lines.find('.line').length).toBe 6
expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(3)
expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(8)
editor.scroller.scrollTop(0)
editor.scroller.trigger 'scroll'
expect(editor.lines.find('.line').length).toBe 6
expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(0)
expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(5)
fit "when the scroller is scrolled to the end, removes lines that become invisible and builds lines that become visible", ->
editor.scroller.scrollBottom(editor.scroller[0].scrollHeight)
editor.scroller.trigger 'scroll'
describe "when scrolling more than the editors height", ->
it "removes lines that become invisible and builds lines that become visible", ->
editor.scroller.scrollBottom(editor.scroller.prop('scrollHeight'))
editor.scroller.trigger 'scroll'
expect(editor.lines.find('.line').length).toBe 6
expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(7)
expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(12)
expect(editor.lines.find('.line').length).toBe 6
expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(7)
expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(12)
editor.scroller.scrollBottom(0)
editor.scroller.trigger 'scroll'
expect(editor.lines.find('.line').length).toBe 6
expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(0)
expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(5)
it "adjusts margins to account for non-rendered lines", ->
editor.scroller.scrollTop(editor.lineHeight * 2.5)
editor.scroller.trigger 'scroll'
it "adjusts the vertical padding of the lines element to account for non-rendered lines", ->
editor.scroller.scrollTop(editor.lineHeight * 2.5)
editor.scroller.trigger 'scroll'
expect(editor.lines.css('padding-top')).toBe "#{2 * editor.lineHeight}px"
expectedPaddingBottom = (buffer.numLines() - 8) * editor.lineHeight
expect(editor.lines.css('padding-bottom')).toBe "#{expectedPaddingBottom}px"
editor.scroller.scrollBottom(editor.scroller.prop('scrollHeight'))
editor.scroller.trigger 'scroll'
expect(editor.lines.css('padding-top')).toBe "#{7 * editor.lineHeight}px"
expect(editor.lines.css('padding-bottom')).toBe "0px"
for line, index in editor.lines.find('.line')
marginTop = $(line).css('margin-top')
marginBottom = $(line).css('margin-bottom')
if index == 0
expectedMarginTop = editor.lineHeight * 2
expect(marginTop).toBe "#{expectedMarginTop}px"
else if index == 5
expectedMarginBottom = (editor.getLastScreenRow() - 7) * editor.lineHeight
expect(marginBottom).toBe "#{expectedMarginBottom}px"
else
expect(marginBottom).toBe '0px'
expect(marginTop).toBe '0px'
it "renders additional lines when the editor is resized", ->
setEditorHeightInLines(editor, 10)
@@ -449,16 +462,6 @@ describe "Editor", ->
expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(0)
expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(9)
# describe "when lines at the beginning of the buffer are not visible on screen when the editor is attached", ->
# beforeEach ->
# editor.attachToDom(heightInLines: 5.5)
# it "only renders the visible lines, giving the first line a margin-top to account for the missing lines", ->
# expect(editor.lines.find('.line').length).toBe 6
# expectedMarginBottom = (buffer.numLines() - 6) * editor.lineHeight
# expect(editor.lines.find('.line:last').css('margin-bottom')).toBe "#{expectedMarginBottom}px"
describe "gutter rendering", ->
it "creates a line number element for each line in the buffer", ->
expect(editor.gutter.find('.line-number').length).toEqual(buffer.numLines())

View File

@@ -250,19 +250,26 @@ class Editor extends View
firstVisibleScreenRow = @getFirstVisibleScreenRow()
lastVisibleScreenRow = @getLastVisibleScreenRow()
console.log "updateLines", firstVisibleScreenRow, lastVisibleScreenRow
# console.log "cursor screen position", @getCursorScreenPosition().inspect()
if firstVisibleScreenRow > @firstRenderedScreenRow
console.log "removing from", @firstRenderedScreenRow, "to", firstVisibleScreenRow - 1
@removeLineElements(@firstRenderedScreenRow, firstVisibleScreenRow - 1)
@lines.css('padding-top', firstVisibleScreenRow * @lineHeight)
console.log @lines
if lastVisibleScreenRow < @lastRenderedScreenRow
@removeLineElements(lastVisibleScreenRow + 1, @lastRenderedScreenRow)
@lines.css('padding-bottom', (@getLastScreenRow() - lastVisibleScreenRow) * @lineHeight)
if firstVisibleScreenRow < @firstRenderedScreenRow
newLinesStartRow = firstVisibleScreenRow
newLinesEndRow = Math.min(@firstRenderedScreenRow - 1, lastVisibleScreenRow)
lineElements = @buildLineElements(newLinesStartRow, newLinesEndRow)
@insertLineElements(newLinesStartRow, lineElements)
@lines.css('padding-top', firstVisibleScreenRow * @lineHeight)
if lastVisibleScreenRow > @lastRenderedScreenRow
startRow = Math.max(@lastRenderedScreenRow + 1, firstVisibleScreenRow)
lineElements = @buildLineElements(startRow, lastVisibleScreenRow)
@insertLineElements(startRow, lineElements)
newLinesStartRow = Math.max(@lastRenderedScreenRow + 1, firstVisibleScreenRow)
newLinesEndRow = lastVisibleScreenRow
lineElements = @buildLineElements(newLinesStartRow, newLinesEndRow)
@insertLineElements(newLinesStartRow, lineElements)
@lines.css('padding-bottom', (@getLastScreenRow() - lastVisibleScreenRow) * @lineHeight)
@firstRenderedScreenRow = firstVisibleScreenRow
@@ -385,8 +392,13 @@ class Editor extends View
@spliceLineElements(startRow, endRow - startRow + 1)
spliceLineElements: (startScreenRow, rowCount, lineElements) ->
startRow = startScreenRow - @firstRenderedScreenRow
if startScreenRow < @firstRenderedScreenRow
startRow = 0
else
startRow = startScreenRow - @firstRenderedScreenRow
endRow = startRow + rowCount
elementToInsertBefore = @lineCache[startRow]
elementsToReplace = @lineCache[startRow...endRow]
@lineCache[startRow...endRow] = lineElements?.toArray() or []