From 2831b43042cfb3646e79fdffe77e3b456cb1cfbc Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 20 Jan 2014 11:14:52 -0700 Subject: [PATCH] Update foldability indicators on changes that don't insert/remove lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- spec/editor-view-spec.coffee | 15 +++++++++++++++ src/gutter.coffee | 23 ++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/spec/editor-view-spec.coffee b/spec/editor-view-spec.coffee index d324001b0..23804de70 100644 --- a/spec/editor-view-spec.coffee +++ b/spec/editor-view-spec.coffee @@ -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) diff --git a/src/gutter.coffee b/src/gutter.coffee index 3cddd9e61..c1097cc51 100644 --- a/src/gutter.coffee +++ b/src/gutter.coffee @@ -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