From 3cf9238d798909f4d82cee70ff269c63b51d10d9 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 13 Aug 2015 16:35:48 -0600 Subject: [PATCH 1/2] Select screen rows when click-dragging in gutter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …Instead of entire buffer rows --- spec/text-editor-component-spec.coffee | 60 +++++++++++++------------- src/text-editor-component.coffee | 37 +++++++++------- 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index 22562032c..ddc0f6d1e 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -2073,123 +2073,123 @@ describe "TextEditorComponent", -> nextAnimationFrame() describe "when the gutter is clicked", -> - it "selects the clicked buffer row", -> + it "selects the clicked screen row", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(1))) - expect(editor.getSelectedScreenRange()).toEqual [[0, 0], [2, 0]] + expect(editor.getSelectedScreenRange()).toEqual [[1, 0], [2, 0]] describe "when the gutter is meta-clicked", -> - it "creates a new selection for the clicked buffer row", -> + it "creates a new selection for the clicked screen row", -> editor.setSelectedScreenRange([[1, 0], [1, 2]]) gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(2), metaKey: true)) - expect(editor.getSelectedScreenRanges()).toEqual [[[1, 0], [1, 2]], [[2, 0], [5, 0]]] + expect(editor.getSelectedScreenRanges()).toEqual [[[1, 0], [1, 2]], [[2, 0], [2, 12]]] gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(7), metaKey: true)) - expect(editor.getSelectedScreenRanges()).toEqual [[[1, 0], [1, 2]], [[2, 0], [5, 0]], [[5, 0], [10, 0]]] + expect(editor.getSelectedScreenRanges()).toEqual [[[1, 0], [1, 2]], [[2, 0], [2, 12]], [[7, 4], [7, 12]]] describe "when the gutter is shift-clicked", -> beforeEach -> editor.setSelectedScreenRange([[7, 4], [7, 6]]) describe "when the clicked row is before the current selection's tail", -> - it "selects to the beginning of the clicked buffer row", -> + it "selects to the beginning of the clicked screen row", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(1), shiftKey: true)) - expect(editor.getSelectedScreenRange()).toEqual [[0, 0], [7, 4]] + expect(editor.getSelectedScreenRange()).toEqual [[1, 0], [7, 4]] describe "when the clicked row is after the current selection's tail", -> - it "selects to the beginning of the buffer row following the clicked buffer row", -> + it "selects to the beginning of the screen row following the clicked screen row", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(11), shiftKey: true)) - expect(editor.getSelectedScreenRange()).toEqual [[7, 4], [16, 0]] + expect(editor.getSelectedScreenRange()).toEqual [[7, 4], [11, 14]] describe "when the gutter is clicked and dragged", -> describe "when dragging downward", -> - it "selects the buffer rows between the start and end of the drag", -> + it "selects the screen rows between the start and end of the drag", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(1))) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(6))) nextAnimationFrame() gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(6))) - expect(editor.getSelectedScreenRange()).toEqual [[0, 0], [10, 0]] + expect(editor.getSelectedScreenRange()).toEqual [[1, 0], [6, 14]] describe "when dragging upward", -> - it "selects the buffer rows between the start and end of the drag", -> + it "selects the screen rows between the start and end of the drag", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(6))) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(1))) nextAnimationFrame() gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(1))) - expect(editor.getSelectedScreenRange()).toEqual [[0, 0], [10, 0]] + expect(editor.getSelectedScreenRange()).toEqual [[1, 0], [6, 14]] describe "when the gutter is meta-clicked and dragged", -> beforeEach -> editor.setSelectedScreenRange([[7, 4], [7, 6]]) describe "when dragging downward", -> - it "selects the buffer rows between the start and end of the drag", -> + it "selects the screen rows between the start and end of the drag", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(1), metaKey: true)) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(3), metaKey: true)) nextAnimationFrame() gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(3), metaKey: true)) - expect(editor.getSelectedScreenRanges()).toEqual [[[7, 4], [7, 6]], [[0, 0], [5, 0]]] + expect(editor.getSelectedScreenRanges()).toEqual [[[7, 4], [7, 6]], [[1, 0], [3, 14]]] it "merges overlapping selections", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(1), metaKey: true)) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(7), metaKey: true)) nextAnimationFrame() gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(7), metaKey: true)) - expect(editor.getSelectedScreenRanges()).toEqual [[[0, 0], [10, 0]]] + expect(editor.getSelectedScreenRanges()).toEqual [[[1, 0], [7, 12]]] describe "when dragging upward", -> - it "selects the buffer rows between the start and end of the drag", -> + it "selects the screen rows between the start and end of the drag", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(17), metaKey: true)) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(11), metaKey: true)) nextAnimationFrame() gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(11), metaKey: true)) - expect(editor.getSelectedScreenRanges()).toEqual [[[7, 4], [7, 6]], [[10, 0], [19, 0]]] + expect(editor.getSelectedScreenRanges()).toEqual [[[7, 4], [7, 6]], [[11, 4], [17, 13]]] it "merges overlapping selections", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(17), metaKey: true)) - gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(9), metaKey: true)) + gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(5), metaKey: true)) nextAnimationFrame() - gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(9), metaKey: true)) - expect(editor.getSelectedScreenRanges()).toEqual [[[5, 0], [19, 0]]] + gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(5), metaKey: true)) + expect(editor.getSelectedScreenRanges()).toEqual [[[5, 0], [17, 13]]] describe "when the gutter is shift-clicked and dragged", -> describe "when the shift-click is below the existing selection's tail", -> describe "when dragging downward", -> - it "selects the buffer rows between the existing selection's tail and the end of the drag", -> + it "selects the screen rows between the existing selection's tail and the end of the drag", -> editor.setSelectedScreenRange([[1, 4], [1, 7]]) gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(7), shiftKey: true)) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(11))) nextAnimationFrame() - expect(editor.getSelectedScreenRange()).toEqual [[1, 4], [16, 0]] + expect(editor.getSelectedScreenRange()).toEqual [[1, 4], [11, 14]] describe "when dragging upward", -> - it "selects the buffer rows between the end of the drag and the tail of the existing selection", -> + it "selects the screen rows between the end of the drag and the tail of the existing selection", -> editor.setSelectedScreenRange([[1, 4], [1, 7]]) gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(11), shiftKey: true)) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(7))) nextAnimationFrame() - expect(editor.getSelectedScreenRange()).toEqual [[1, 4], [10, 0]] + expect(editor.getSelectedScreenRange()).toEqual [[1, 4], [7, 12]] describe "when the shift-click is above the existing selection's tail", -> describe "when dragging upward", -> - it "selects the buffer rows between the end of the drag and the tail of the existing selection", -> + it "selects the screen rows between the end of the drag and the tail of the existing selection", -> editor.setSelectedScreenRange([[7, 4], [7, 6]]) gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(3), shiftKey: true)) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(1))) nextAnimationFrame() - expect(editor.getSelectedScreenRange()).toEqual [[0, 0], [7, 4]] + expect(editor.getSelectedScreenRange()).toEqual [[1, 0], [7, 4]] describe "when dragging downward", -> - it "selects the buffer rows between the existing selection's tail and the end of the drag", -> + it "selects the screen rows between the existing selection's tail and the end of the drag", -> editor.setSelectedScreenRange([[7, 4], [7, 6]]) gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(1), shiftKey: true)) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(3))) nextAnimationFrame() - expect(editor.getSelectedScreenRange()).toEqual [[2, 0], [7, 4]] + expect(editor.getSelectedScreenRange()).toEqual [[3, 2], [7, 4]] describe "focus handling", -> inputNode = null @@ -3189,7 +3189,7 @@ describe "TextEditorComponent", -> {clientX, clientY} clientCoordinatesForScreenRowInGutter = (screenRow) -> - positionOffset = wrapperNode.pixelPositionForScreenPosition([screenRow, 1]) + positionOffset = wrapperNode.pixelPositionForScreenPosition([screenRow, Infinity]) gutterClientRect = componentNode.querySelector('.gutter').getBoundingClientRect() clientX = gutterClientRect.left + positionOffset.left - editor.getScrollLeft() clientY = gutterClientRect.top + positionOffset.top - editor.getScrollTop() diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index a46b352a3..101d27254 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -419,35 +419,42 @@ class TextEditorComponent @onGutterClick(event) onGutterClick: (event) => - clickedBufferRow = @editor.bufferRowForScreenRow(@screenPositionForMouseEvent(event).row) - @editor.setSelectedBufferRange([[clickedBufferRow, 0], [clickedBufferRow + 1, 0]], preserveFolds: true) - @handleGutterDrag(clickedBufferRow) + clickedScreenRow = @screenPositionForMouseEvent(event).row + startPosition = @editor.clipScreenPosition([clickedScreenRow, 0], skipSoftWrapIndentation: true) + endPosition = [clickedScreenRow + 1, 0] + @editor.setSelectedScreenRange([startPosition, endPosition], preserveFolds: true) + @handleGutterDrag(clickedScreenRow) onGutterMetaClick: (event) => - clickedBufferRow = @editor.bufferRowForScreenRow(@screenPositionForMouseEvent(event).row) - @editor.addSelectionForBufferRange([[clickedBufferRow, 0], [clickedBufferRow + 1, 0]], preserveFolds: true) - @handleGutterDrag(clickedBufferRow) + clickedScreenRow = @screenPositionForMouseEvent(event).row + startPosition = @editor.clipScreenPosition([clickedScreenRow, 0], skipSoftWrapIndentation: true) + endPosition = [clickedScreenRow + 1, 0] + @editor.addSelectionForScreenRange([startPosition, endPosition], preserveFolds: true) + @handleGutterDrag(clickedScreenRow) onGutterShiftClick: (event) => - clickedBufferRow = @editor.bufferRowForScreenRow(@screenPositionForMouseEvent(event).row) - tailBufferPosition = @editor.getLastSelection().getTailBufferPosition() + clickedScreenRow = @screenPositionForMouseEvent(event).row + tailScreenPosition = @editor.getLastSelection().getTailScreenPosition() - if clickedBufferRow < tailBufferPosition.row - @editor.selectToBufferPosition([clickedBufferRow, 0], true) + if clickedScreenRow < tailScreenPosition.row + selectedPosition = @editor.clipScreenPosition([clickedScreenRow, 0], skipSoftWrapIndentation: true) + @editor.selectToScreenPosition(selectedPosition, true) else - @editor.selectToBufferPosition([clickedBufferRow + 1, 0], true) + @editor.selectToScreenPosition([clickedScreenRow + 1, 0], true) - @handleGutterDrag(tailBufferPosition.row, tailBufferPosition.column) + @handleGutterDrag(tailScreenPosition.row, tailScreenPosition.column) handleGutterDrag: (tailRow, tailColumn) -> tailPosition = [tailRow, tailColumn] if tailColumn? @handleDragUntilMouseUp (screenPosition) => - dragRow = @editor.bufferPositionForScreenPosition(screenPosition).row + dragRow = screenPosition.row if dragRow < tailRow - @editor.getLastSelection().setBufferRange([[dragRow, 0], tailPosition ? [tailRow + 1, 0]], reversed: true, autoscroll: false, preserveFolds: true) + startPosition = @editor.clipScreenPosition([dragRow, 0], skipSoftWrapIndentation: true) + @editor.getLastSelection().setScreenRange([startPosition, tailPosition ? [tailRow + 1, 0]], reversed: true, autoscroll: false, preserveFolds: true) else - @editor.getLastSelection().setBufferRange([tailPosition ? [tailRow, 0], [dragRow + 1, 0]], reversed: false, autoscroll: false, preserveFolds: true) + startPosition = tailPosition ? @editor.clipScreenPosition([tailRow, 0], skipSoftWrapIndentation: true) + @editor.getLastSelection().setScreenRange([startPosition, [dragRow + 1, 0]], reversed: false, autoscroll: false, preserveFolds: true) @editor.getLastCursor().autoscroll() onStylesheetsChanged: (styleElement) => From 31bdd563ed7651f75028435df3cbf35078c1c447 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 19 Aug 2015 12:40:14 -0600 Subject: [PATCH 2/2] Select by buffer row on gutter click, but by screen row on gutter drag --- spec/text-editor-component-spec.coffee | 42 +++++++++++++------------- src/text-editor-component.coffee | 41 +++++++++++++------------ 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index ddc0f6d1e..6ae37a7fd 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -2073,84 +2073,84 @@ describe "TextEditorComponent", -> nextAnimationFrame() describe "when the gutter is clicked", -> - it "selects the clicked screen row", -> + it "selects the clicked buffer row", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(1))) - expect(editor.getSelectedScreenRange()).toEqual [[1, 0], [2, 0]] + expect(editor.getSelectedScreenRange()).toEqual [[0, 0], [2, 0]] describe "when the gutter is meta-clicked", -> - it "creates a new selection for the clicked screen row", -> + it "creates a new selection for the clicked buffer row", -> editor.setSelectedScreenRange([[1, 0], [1, 2]]) gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(2), metaKey: true)) - expect(editor.getSelectedScreenRanges()).toEqual [[[1, 0], [1, 2]], [[2, 0], [2, 12]]] + expect(editor.getSelectedScreenRanges()).toEqual [[[1, 0], [1, 2]], [[2, 0], [5, 0]]] gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(7), metaKey: true)) - expect(editor.getSelectedScreenRanges()).toEqual [[[1, 0], [1, 2]], [[2, 0], [2, 12]], [[7, 4], [7, 12]]] + expect(editor.getSelectedScreenRanges()).toEqual [[[1, 0], [1, 2]], [[2, 0], [5, 0]], [[5, 0], [10, 0]]] describe "when the gutter is shift-clicked", -> beforeEach -> editor.setSelectedScreenRange([[7, 4], [7, 6]]) describe "when the clicked row is before the current selection's tail", -> - it "selects to the beginning of the clicked screen row", -> + it "selects to the beginning of the clicked buffer row", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(1), shiftKey: true)) - expect(editor.getSelectedScreenRange()).toEqual [[1, 0], [7, 4]] + expect(editor.getSelectedScreenRange()).toEqual [[0, 0], [7, 4]] describe "when the clicked row is after the current selection's tail", -> - it "selects to the beginning of the screen row following the clicked screen row", -> + it "selects to the beginning of the screen row following the clicked buffer row", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(11), shiftKey: true)) - expect(editor.getSelectedScreenRange()).toEqual [[7, 4], [11, 14]] + expect(editor.getSelectedScreenRange()).toEqual [[7, 4], [16, 0]] describe "when the gutter is clicked and dragged", -> describe "when dragging downward", -> - it "selects the screen rows between the start and end of the drag", -> + it "selects the buffer row containing the click, then screen rows until the end of the drag", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(1))) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(6))) nextAnimationFrame() gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(6))) - expect(editor.getSelectedScreenRange()).toEqual [[1, 0], [6, 14]] + expect(editor.getSelectedScreenRange()).toEqual [[0, 0], [6, 14]] describe "when dragging upward", -> - it "selects the screen rows between the start and end of the drag", -> + it "selects the buffer row containing the click, then screen rows until the end of the drag", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(6))) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(1))) nextAnimationFrame() gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(1))) - expect(editor.getSelectedScreenRange()).toEqual [[1, 0], [6, 14]] + expect(editor.getSelectedScreenRange()).toEqual [[1, 0], [10, 0]] describe "when the gutter is meta-clicked and dragged", -> beforeEach -> editor.setSelectedScreenRange([[7, 4], [7, 6]]) describe "when dragging downward", -> - it "selects the screen rows between the start and end of the drag", -> + it "adds a selection from the buffer row containing the click to the screen row containing the end of the drag", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(1), metaKey: true)) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(3), metaKey: true)) nextAnimationFrame() gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(3), metaKey: true)) - expect(editor.getSelectedScreenRanges()).toEqual [[[7, 4], [7, 6]], [[1, 0], [3, 14]]] + expect(editor.getSelectedScreenRanges()).toEqual [[[7, 4], [7, 6]], [[0, 0], [3, 14]]] - it "merges overlapping selections", -> + it "merges overlapping selections on mouseup", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(1), metaKey: true)) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(7), metaKey: true)) nextAnimationFrame() gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(7), metaKey: true)) - expect(editor.getSelectedScreenRanges()).toEqual [[[1, 0], [7, 12]]] + expect(editor.getSelectedScreenRanges()).toEqual [[[0, 0], [7, 12]]] describe "when dragging upward", -> - it "selects the screen rows between the start and end of the drag", -> + it "adds a selection from the buffer row containing the click to the screen row containing the end of the drag", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(17), metaKey: true)) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(11), metaKey: true)) nextAnimationFrame() gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(11), metaKey: true)) - expect(editor.getSelectedScreenRanges()).toEqual [[[7, 4], [7, 6]], [[11, 4], [17, 13]]] + expect(editor.getSelectedScreenRanges()).toEqual [[[7, 4], [7, 6]], [[11, 4], [19, 0]]] - it "merges overlapping selections", -> + it "merges overlapping selections on mouseup", -> gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(17), metaKey: true)) gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(5), metaKey: true)) nextAnimationFrame() gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(5), metaKey: true)) - expect(editor.getSelectedScreenRanges()).toEqual [[[5, 0], [17, 13]]] + expect(editor.getSelectedScreenRanges()).toEqual [[[5, 0], [19, 0]]] describe "when the gutter is shift-clicked and dragged", -> describe "when the shift-click is below the existing selection's tail", -> diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index 101d27254..3386eb184 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -420,41 +420,42 @@ class TextEditorComponent onGutterClick: (event) => clickedScreenRow = @screenPositionForMouseEvent(event).row - startPosition = @editor.clipScreenPosition([clickedScreenRow, 0], skipSoftWrapIndentation: true) - endPosition = [clickedScreenRow + 1, 0] - @editor.setSelectedScreenRange([startPosition, endPosition], preserveFolds: true) - @handleGutterDrag(clickedScreenRow) + clickedBufferRow = @editor.bufferRowForScreenRow(clickedScreenRow) + initialScreenRange = @editor.screenRangeForBufferRange([[clickedBufferRow, 0], [clickedBufferRow + 1, 0]]) + @editor.setSelectedScreenRange(initialScreenRange, preserveFolds: true) + @handleGutterDrag(initialScreenRange) onGutterMetaClick: (event) => clickedScreenRow = @screenPositionForMouseEvent(event).row - startPosition = @editor.clipScreenPosition([clickedScreenRow, 0], skipSoftWrapIndentation: true) - endPosition = [clickedScreenRow + 1, 0] - @editor.addSelectionForScreenRange([startPosition, endPosition], preserveFolds: true) - @handleGutterDrag(clickedScreenRow) + clickedBufferRow = @editor.bufferRowForScreenRow(clickedScreenRow) + initialScreenRange = @editor.screenRangeForBufferRange([[clickedBufferRow, 0], [clickedBufferRow + 1, 0]]) + @editor.addSelectionForScreenRange(initialScreenRange, preserveFolds: true) + @handleGutterDrag(initialScreenRange) onGutterShiftClick: (event) => - clickedScreenRow = @screenPositionForMouseEvent(event).row tailScreenPosition = @editor.getLastSelection().getTailScreenPosition() + clickedScreenRow = @screenPositionForMouseEvent(event).row + clickedBufferRow = @editor.bufferRowForScreenRow(clickedScreenRow) + clickedLineScreenRange = @editor.screenRangeForBufferRange([[clickedBufferRow, 0], [clickedBufferRow + 1, 0]]) if clickedScreenRow < tailScreenPosition.row - selectedPosition = @editor.clipScreenPosition([clickedScreenRow, 0], skipSoftWrapIndentation: true) - @editor.selectToScreenPosition(selectedPosition, true) + @editor.selectToScreenPosition(clickedLineScreenRange.start, true) else - @editor.selectToScreenPosition([clickedScreenRow + 1, 0], true) + @editor.selectToScreenPosition(clickedLineScreenRange.end, true) - @handleGutterDrag(tailScreenPosition.row, tailScreenPosition.column) - - handleGutterDrag: (tailRow, tailColumn) -> - tailPosition = [tailRow, tailColumn] if tailColumn? + @handleGutterDrag(new Range(tailScreenPosition, tailScreenPosition)) + handleGutterDrag: (initialRange) -> @handleDragUntilMouseUp (screenPosition) => dragRow = screenPosition.row - if dragRow < tailRow + if dragRow < initialRange.start.row startPosition = @editor.clipScreenPosition([dragRow, 0], skipSoftWrapIndentation: true) - @editor.getLastSelection().setScreenRange([startPosition, tailPosition ? [tailRow + 1, 0]], reversed: true, autoscroll: false, preserveFolds: true) + screenRange = new Range(startPosition, startPosition).union(initialRange) + @editor.getLastSelection().setScreenRange(screenRange, reversed: true, autoscroll: false, preserveFolds: true) else - startPosition = tailPosition ? @editor.clipScreenPosition([tailRow, 0], skipSoftWrapIndentation: true) - @editor.getLastSelection().setScreenRange([startPosition, [dragRow + 1, 0]], reversed: false, autoscroll: false, preserveFolds: true) + endPosition = [dragRow + 1, 0] + screenRange = new Range(endPosition, endPosition).union(initialRange) + @editor.getLastSelection().setScreenRange(screenRange, reversed: false, autoscroll: false, preserveFolds: true) @editor.getLastCursor().autoscroll() onStylesheetsChanged: (styleElement) =>