diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index 645f4c54f..dcb5a17ca 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -2460,6 +2460,39 @@ describe "Editor", -> expect(editor.getCursorBufferPosition()).toEqual [3, 0] + describe "when a selection starts/stops intersecting a fold", -> + it "adds/removes the 'selected' class to the fold's line element", -> + editor.createFold(2, 4) + + editor.setSelectionBufferRange([[1, 0], [2, 0]], reverse: true) + expect(editor.lineElementForScreenRow(2)).toMatchSelector('.fold.selected') + + editor.setSelectionBufferRange([[1, 0], [1, 1]]) + expect(editor.lineElementForScreenRow(2)).not.toMatchSelector('.fold.selected') + + editor.setSelectionBufferRange([[1, 0], [5, 0]]) + expect(editor.lineElementForScreenRow(2)).toMatchSelector('.fold.selected') + + editor.setCursorScreenPosition([3,0]) + expect(editor.lineElementForScreenRow(2)).not.toMatchSelector('.fold.selected') + + editor.setCursorScreenPosition([2,0]) + expect(editor.lineElementForScreenRow(2)).toMatchSelector('.fold.selected') + + describe "when a selected fold is scrolled into view (and the fold line was not previously rendered)", -> + it "renders the fold's line element with the 'selected' class", -> + setEditorHeightInLines(editor, 5) + + editor.createFold(2, 4) + editor.setSelectionBufferRange([[1, 0], [5, 0]]) + expect(editor.visibleLines.find('.fold.selected')).toExist() + + editor.scrollToBottom() + expect(editor.visibleLines.find('.fold.selected')).not.toExist() + + editor.scrollTop(0) + expect(editor.lineElementForScreenRow(2)).toMatchSelector('.fold.selected') + describe "editor-path-change event", -> it "emits event when buffer's path is changed", -> editor = new Editor diff --git a/src/app/composite-selection.coffee b/src/app/composite-selection.coffee index 2d470b8f2..5a6887b45 100644 --- a/src/app/composite-selection.coffee +++ b/src/app/composite-selection.coffee @@ -74,6 +74,10 @@ class CompositeSeleciton getText: -> @getLastSelection().getText() + intersectsBufferRange: (bufferRange) -> + _.any @getSelections(), (selection) -> + selection.intersectsBufferRange(bufferRange) + expandSelectionsForward: (fn) -> fn(selection) for selection in @getSelections() @mergeIntersectingSelections() diff --git a/src/app/editor.coffee b/src/app/editor.coffee index e544cbcca..2cecb9487 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -62,6 +62,7 @@ class Editor extends View requireStylesheet 'theme/twilight.css' @id = Editor.idCounter++ + @lineCache = [] @bindKeys() @autoIndent = true @buildCursorAndSelection() @@ -335,13 +336,25 @@ class Editor extends View getLastVisibleScreenRow: -> Math.ceil((@scrollTop() + @scrollView.height()) / @lineHeight) - 1 + highlightSelectedFolds: -> + screenLines = @screenLinesForRows(@firstRenderedScreenRow, @lastRenderedScreenRow) + for screenLine, i in screenLines + if fold = screenLine.fold + screenRow = @firstRenderedScreenRow + i + element = @lineElementForScreenRow(screenRow) + if @compositeSelection.intersectsBufferRange(fold.getBufferRange()) + + element.addClass('selected') + else + element.removeClass('selected') + getScreenLines: -> @renderer.getLines() screenLineForRow: (start) -> @renderer.lineForRow(start) - linesForRows: (start, end) -> + screenLinesForRows: (start, end) -> @renderer.linesForRows(start, end) screenLineCount: -> @@ -468,11 +481,14 @@ class Editor extends View charWidth = @charWidth charHeight = @charHeight lines = @renderer.linesForRows(startRow, endRow) + compositeSelection = @compositeSelection $$ -> for line in lines if fold = line.fold lineAttributes = { class: 'fold line', 'fold-id': fold.id } + if compositeSelection.intersectsBufferRange(fold.getBufferRange()) + lineAttributes.class += ' selected' else lineAttributes = { class: 'line' } @div lineAttributes, => @@ -514,8 +530,9 @@ class Editor extends View elementsToReplace.forEach (element) => lines.removeChild(element) - getLineElement: (row) -> - @lineCache[row] + lineElementForScreenRow: (screenRow) -> + element = @lineCache[screenRow - @firstRenderedScreenRow] + $(element) toggleSoftWrap: -> @setSoftWrap(not @softWrap) @@ -747,6 +764,9 @@ class Editor extends View @scrollVertically(pixelPosition) @scrollHorizontally(pixelPosition) + scrollToBottom: -> + @scrollBottom(@scrollView.prop('scrollHeight')) + scrollVertically: (pixelPosition) -> linesInView = @scrollView.height() / @lineHeight maxScrollMargin = Math.floor((linesInView - 1) / 2) diff --git a/src/app/fold.coffee b/src/app/fold.coffee index 244a36bd0..280b94f78 100644 --- a/src/app/fold.coffee +++ b/src/app/fold.coffee @@ -18,6 +18,9 @@ class Fold inspect: -> "Fold(#{@startRow}, #{@endRow})" + getBufferRange: -> + new Range([@startRow, 0], [@endRow, Infinity]) + getBufferDelta: -> new Point(@endRow - @startRow + 1, 0) diff --git a/src/app/selection.coffee b/src/app/selection.coffee index 882940f69..4e83b23df 100644 --- a/src/app/selection.coffee +++ b/src/app/selection.coffee @@ -45,6 +45,8 @@ class Selection extends View @clearRegions() range = @getScreenRange() + + @editor.highlightSelectedFolds() return if range.isEmpty() rowSpan = range.end.row - range.start.row @@ -57,6 +59,7 @@ class Selection extends View @appendRegion(rowSpan - 1, { row: range.start.row + 1, column: 0}, null) @appendRegion(1, { row: range.end.row, column: 0 }, range.end) + appendRegion: (rows, start, end) -> { lineHeight, charWidth } = @editor css = @editor.pixelPositionForScreenPosition(start) @@ -80,8 +83,7 @@ class Selection extends View else new Range(@cursor.getScreenPosition(), @cursor.getScreenPosition()) - setScreenRange: (range, options={}) -> - { reverse } = options + setScreenRange: (range, {reverse}={}) -> { start, end } = range [start, end] = [end, start] if reverse @@ -97,6 +99,9 @@ class Selection extends View getText: -> @editor.buffer.getTextInRange @getBufferRange() + intersectsBufferRange: (bufferRange) -> + @getBufferRange().intersectsWith(bufferRange) + insertText: (text) -> { text, shouldOutdent } = @autoIndentText(text) oldBufferRange = @getBufferRange() diff --git a/static/theme/twilight.css b/static/theme/twilight.css index f83b9e705..97ceea195 100644 --- a/static/theme/twilight.css +++ b/static/theme/twilight.css @@ -74,6 +74,11 @@ color:#D2A8A1; color: #969696; } +.fold.selected { + background-color: #82715C; + color: #969696; +} + .support.function { color:#DAD085; }