Update foldability indicators on changes that don't insert/remove lines

On changes that insert/remove lines, we redraw the entire gutter, which
ensures the foldability markers are up to date. But other kinds of
changes could change the foldability of lines… if a line becomes
commented or its indentation changes, the foldability of that line and
the lines above and below could be affected. For now, the gutter
understands this fact and updates the foldability for the region
extending from one line before to one line after each change. Someday
I'd like the view logic to not bake in knowledge of the folding rules,
but this works for now.
This commit is contained in:
Nathan Sobo
2014-01-20 11:14:52 -07:00
parent 3eb7c9d767
commit 2831b43042
2 changed files with 37 additions and 1 deletions

View File

@@ -1829,6 +1829,21 @@ describe "EditorView", ->
expect(editorView.gutter.find('.line-number:eq(3)')).not.toHaveClass 'foldable'
expect(editorView.gutter.find('.line-number:eq(4)')).toHaveClass 'foldable'
# changes to indentation update foldability
editor.setIndentationForBufferRow(1, 0)
expect(editorView.gutter.find('.line-number:eq(0)')).not.toHaveClass 'foldable'
expect(editorView.gutter.find('.line-number:eq(1)')).toHaveClass 'foldable'
# changes to comments update foldability
editor.toggleLineCommentsForBufferRows(2, 3)
expect(editorView.gutter.find('.line-number:eq(2)')).toHaveClass 'foldable'
expect(editorView.gutter.find('.line-number:eq(3)')).not.toHaveClass 'foldable'
editor.toggleLineCommentForBufferRow(2)
expect(editorView.gutter.find('.line-number:eq(2)')).not.toHaveClass 'foldable'
expect(editorView.gutter.find('.line-number:eq(3)')).not.toHaveClass 'foldable'
editor.toggleLineCommentForBufferRow(4)
expect(editorView.gutter.find('.line-number:eq(3)')).toHaveClass 'foldable'
describe "when lines are inserted", ->
it "re-renders the correct line number range in the gutter", ->
editorView.scrollTop(3 * editorView.lineHeight)

View File

@@ -151,10 +151,12 @@ class Gutter extends View
updateAllLines = true
break
# If a change added or removed lines, just rebuild the entire gutter
if updateAllLines
@lineNumbers[0].innerHTML = @buildLineElementsHtml(startScreenRow, endScreenRow)
# Handle changes that didn't add/remove lines more optimally
else
# When scrolling or adding/removing lines, we just add/remove lines from the ends.
if startScreenRow < @firstScreenRow
@prependLineElements(@buildLineElements(startScreenRow, @firstScreenRow-1))
else if startScreenRow != @firstScreenRow
@@ -165,6 +167,8 @@ class Gutter extends View
else if endScreenRow != @lastScreenRow
@removeLineElements(endScreenRow - @lastScreenRow)
@updateFoldableClasses(changes)
@firstScreenRow = startScreenRow
@lastScreenRow = endScreenRow
@highlightedRows = null
@@ -219,6 +223,23 @@ class Gutter extends View
html
# Private: Called to update the 'foldable' class of line numbers when there's
# a change to the display buffer that doesn't regenerate all the line numbers
# anyway.
updateFoldableClasses: (changes) ->
editor = @getEditor()
for {start, end} in changes when start <= @lastScreenRow
startScreenRow = Math.max(start - 1, @firstScreenRow)
endScreenRow = Math.min(end + 1, @lastScreenRow)
lastBufferRow = null
for bufferRow in editor.bufferRowsForScreenRows(startScreenRow, endScreenRow) when bufferRow isnt lastBufferRow
lastBufferRow = bufferRow
lineNumberElement = @getLineNumberElement(bufferRow)[0]
if editor.isFoldableAtBufferRow(bufferRow)
lineNumberElement.classList.add('foldable')
else
lineNumberElement.classList.remove('foldable')
removeLineHighlights: ->
return unless @highlightedLineNumbers
for line in @highlightedLineNumbers