From fdae5fd89c12c75c8945b1f30de641fa90f7a4f9 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Mon, 29 Apr 2013 14:59:13 -0700 Subject: [PATCH] Listen for mouse events on scrollView instead of renderedLines It was not possible to click on the lower part of the last line when the editor was scrollable and listening for mousedown events on renderedLines. Closes #464 --- spec/app/editor-spec.coffee | 164 +++++++++++++++++++----------------- src/app/editor.coffee | 7 +- 2 files changed, 87 insertions(+), 84 deletions(-) diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index 8e9c97cf7..09792ed8a 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -371,17 +371,23 @@ describe "Editor", -> describe "single-click", -> it "re-positions the cursor to the clicked row / column", -> expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 10]) + editor.scrollView.trigger mousedownEvent(editor: editor, point: [3, 10]) expect(editor.getCursorScreenPosition()).toEqual(row: 3, column: 10) describe "when the lines are scrolled to the right", -> it "re-positions the cursor on the clicked location", -> setEditorWidthInChars(editor, 30) expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 30]) # scrolls lines to the right - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 50]) + editor.scrollView.trigger mousedownEvent(editor: editor, point: [3, 30]) # scrolls lines to the right + editor.scrollView.trigger mousedownEvent(editor: editor, point: [3, 50]) expect(editor.getCursorBufferPosition()).toEqual(row: 3, column: 50) + describe "when clicking on the last line", -> + it "re-positions the cursor on the last line (regression)", -> + expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) + editor.scrollView.trigger mousedownEvent(editor: editor, point: [13, 20]) + expect(editor.getCursorScreenPosition()).toEqual(row: 12, column: 2) + describe "when the editor is using a variable-width font", -> beforeEach -> editor.setFontFamily('sans-serif') @@ -391,35 +397,35 @@ describe "Editor", -> it "positions the cursor to the clicked row and column", -> {top, left} = editor.pixelOffsUtilsetForScreenPosition([3, 30]) - editor.renderedLines.trigger mousedownEvent(pageX: left, pageY: top) + editor.scrollView.trigger mousedownEvent(pageX: left, pageY: top) expect(editor.getCursorScreenPosition()).toEqual [3, 30] describe "double-click", -> it "selects the word under the cursor, and expands the selection wordwise in either direction on a subsequent shift-click", -> expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [8, 24], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [8, 24], originalEvent: {detail: 2}) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [8, 24], originalEvent: {detail: 1}) + editor.scrollView.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [8, 24], originalEvent: {detail: 2}) + editor.scrollView.trigger 'mouseup' expect(editor.getSelectedText()).toBe "concat" - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [8, 7], shiftKey: true) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [8, 7], shiftKey: true) + editor.scrollView.trigger 'mouseup' expect(editor.getSelectedText()).toBe "return sort(left).concat" it "stops selecting by word when the selection is emptied", -> expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 2}) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 1}) + editor.scrollView.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 2}) + editor.scrollView.trigger 'mouseup' expect(editor.getSelectedText()).toBe "quicksort" - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 10]) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [3, 10]) + editor.scrollView.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 12], originalEvent: {detail: 1}, shiftKey: true) + editor.scrollView.trigger mousedownEvent(editor: editor, point: [3, 12], originalEvent: {detail: 1}, shiftKey: true) expect(editor.getSelectedBufferRange()).toEqual [[3, 10], [3, 12]] describe "triple/quardruple/etc-click", -> @@ -427,74 +433,74 @@ describe "Editor", -> expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) # Triple click - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [1, 8], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [1, 8], originalEvent: {detail: 2}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [1, 8], originalEvent: {detail: 3}) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [1, 8], originalEvent: {detail: 1}) + editor.scrollView.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [1, 8], originalEvent: {detail: 2}) + editor.scrollView.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [1, 8], originalEvent: {detail: 3}) + editor.scrollView.trigger 'mouseup' expect(editor.getSelectedText()).toBe " var sort = function(items) {\n" # Quad click - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [2, 3], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [2, 3], originalEvent: {detail: 2}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [2, 3], originalEvent: {detail: 3}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [2, 3], originalEvent: {detail: 4}) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [2, 3], originalEvent: {detail: 1}) + editor.scrollView.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [2, 3], originalEvent: {detail: 2}) + editor.scrollView.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [2, 3], originalEvent: {detail: 3}) + editor.scrollView.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [2, 3], originalEvent: {detail: 4}) + editor.scrollView.trigger 'mouseup' expect(editor.getSelectedText()).toBe " if (items.length <= 1) return items;\n" it "expands the selection linewise in either direction on a subsequent shift-click, but stops selecting linewise once the selection is emptied", -> - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 8], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 8], originalEvent: {detail: 2}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 8], originalEvent: {detail: 3}) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [4, 8], originalEvent: {detail: 1}) + editor.scrollView.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [4, 8], originalEvent: {detail: 2}) + editor.scrollView.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [4, 8], originalEvent: {detail: 3}) + editor.scrollView.trigger 'mouseup' expect(editor.getSelectedBufferRange()).toEqual [[4, 0], [5, 0]] - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [1, 8], originalEvent: {detail: 1}, shiftKey: true) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [1, 8], originalEvent: {detail: 1}, shiftKey: true) + editor.scrollView.trigger 'mouseup' expect(editor.getSelectedBufferRange()).toEqual [[1, 0], [5, 0]] - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [2, 8], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [2, 8], originalEvent: {detail: 1}) + editor.scrollView.trigger 'mouseup' expect(editor.getSelection().isEmpty()).toBeTruthy() - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 8], originalEvent: {detail: 1}, shiftKey: true) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [3, 8], originalEvent: {detail: 1}, shiftKey: true) + editor.scrollView.trigger 'mouseup' expect(editor.getSelectedBufferRange()).toEqual [[2, 8], [3, 8]] describe "shift-click", -> it "selects from the cursor's current location to the clicked location", -> editor.setCursorScreenPosition([4, 7]) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true) + editor.scrollView.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true) expect(editor.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] describe "shift-double-click", -> it "expands the selection on the first click and ignores the second click", -> editor.setCursorScreenPosition([4, 7]) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 1 }) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 1 }) + editor.scrollView.trigger 'mouseup' expect(editor.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 2 }) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 2 }) + editor.scrollView.trigger 'mouseup' expect(editor.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] describe "shift-triple-click", -> it "expands the selection on the first click and ignores the second click", -> editor.setCursorScreenPosition([4, 7]) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 1 }) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 1 }) + editor.scrollView.trigger 'mouseup' expect(editor.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 2 }) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 3 }) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 2 }) + editor.scrollView.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 3 }) + editor.scrollView.trigger 'mouseup' expect(editor.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] describe "meta-click", -> @@ -504,7 +510,7 @@ describe "Editor", -> editor.setCursorBufferPosition([3, 0]) editor.scrollTop(editor.lineHeight * 6) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [6, 0], metaKey: true) + editor.scrollView.trigger mousedownEvent(editor: editor, point: [6, 0], metaKey: true) expect(editor.scrollTop()).toBe editor.lineHeight * (6 - editor.vScrollMargin) [cursor1, cursor2] = editor.getCursorViews() @@ -519,7 +525,7 @@ describe "Editor", -> editor.css(position: 'absolute', top: 10, left: 10) # start - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 10]) + editor.scrollView.trigger mousedownEvent(editor: editor, point: [4, 10]) # moving changes selection $(document).trigger mousemoveEvent(editor: editor, point: [5, 27]) @@ -533,7 +539,7 @@ describe "Editor", -> $(document).trigger 'mouseup' # moving after mouse up should not change selection - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [8, 8]) + editor.scrollView.trigger mousemoveEvent(editor: editor, point: [8, 8]) range = editor.getSelection().getScreenRange() expect(range.start).toEqual({row: 4, column: 10}) @@ -547,7 +553,7 @@ describe "Editor", -> spyOn(window, 'setInterval').andCallFake (fn) -> intervalFns.push(fn) # start - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [12, 0]) + editor.scrollView.trigger mousedownEvent(editor: editor, point: [12, 0]) # moving changes selection $(document).trigger mousemoveEvent(editor: editor, pageX: 0, pageY: -15) @@ -564,7 +570,7 @@ describe "Editor", -> event = mousedownEvent(editor: editor, point: [4, 10]) event.originalEvent.which = 2 - editor.renderedLines.trigger(event) + editor.scrollView.trigger(event) $(document).trigger mousemoveEvent(editor: editor, point: [5, 27]) $(document).trigger 'mouseup' @@ -578,7 +584,7 @@ describe "Editor", -> event = mousedownEvent(editor: editor, point: [4, 10]) event.ctrlKey = true - editor.renderedLines.trigger(event) + editor.scrollView.trigger(event) $(document).trigger mousemoveEvent(editor: editor, point: [5, 27]) $(document).trigger 'mouseup' @@ -589,25 +595,25 @@ describe "Editor", -> describe "double-click and drag", -> it "selects the word under the cursor, then continues to select by word in either direction as the mouse is dragged", -> expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 2}) + editor.scrollView.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 1}) + editor.scrollView.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 2}) expect(editor.getSelectedText()).toBe "quicksort" - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [1, 8]) + editor.scrollView.trigger mousemoveEvent(editor: editor, point: [1, 8]) expect(editor.getSelectedBufferRange()).toEqual [[0, 4], [1, 10]] expect(editor.getCursorBufferPosition()).toEqual [1, 10] - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [0, 1]) + editor.scrollView.trigger mousemoveEvent(editor: editor, point: [0, 1]) expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 13]] expect(editor.getCursorBufferPosition()).toEqual [0, 0] - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger 'mouseup' expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 13]] # shift-clicking still selects by word, but does not preserve the initial range - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 25], originalEvent: {detail: 1}, shiftKey: true) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [5, 25], originalEvent: {detail: 1}, shiftKey: true) + editor.scrollView.trigger 'mouseup' expect(editor.getSelectedBufferRange()).toEqual [[0, 13], [5, 27]] describe "triple-click and drag", -> @@ -615,20 +621,20 @@ describe "Editor", -> editor.attachToDom() # triple click - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 1}) + editor.scrollView.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 1}) $(document).trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 2}) + editor.scrollView.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 2}) $(document).trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 3}) + editor.scrollView.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 3}) expect(editor.getSelectedBufferRange()).toEqual [[4, 0], [5, 0]] # moving changes selection linewise - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [5, 27]) + editor.scrollView.trigger mousemoveEvent(editor: editor, point: [5, 27]) expect(editor.getSelectedBufferRange()).toEqual [[4, 0], [6, 0]] expect(editor.getCursorBufferPosition()).toEqual [6, 0] # moving changes selection linewise - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [2, 27]) + editor.scrollView.trigger mousemoveEvent(editor: editor, point: [2, 27]) expect(editor.getSelectedBufferRange()).toEqual [[2, 0], [5, 0]] expect(editor.getCursorBufferPosition()).toEqual [2, 0] @@ -637,13 +643,13 @@ describe "Editor", -> describe "meta-click and drag", -> it "adds an additional selection", -> - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 10]) - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [5, 27]) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [4, 10]) + editor.scrollView.trigger mousemoveEvent(editor: editor, point: [5, 27]) + editor.scrollView.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [6, 10], metaKey: true) - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [8, 27], metaKey: true) - editor.renderedLines.trigger 'mouseup' + editor.scrollView.trigger mousedownEvent(editor: editor, point: [6, 10], metaKey: true) + editor.scrollView.trigger mousemoveEvent(editor: editor, point: [8, 27], metaKey: true) + editor.scrollView.trigger 'mouseup' selections = editor.getSelections() expect(selections.length).toBe 2 diff --git a/src/app/editor.coffee b/src/app/editor.coffee index a718bcb85..f1189d207 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -835,13 +835,12 @@ class Editor extends View $(clickedElement).trigger(e) false if @isFocused - @renderedLines.on 'mousedown', '.fold.line', (e) => + @scrollView.on 'mousedown', '.fold.line', (e) => @destroyFold($(e.currentTarget).attr('fold-id')) false - onMouseDown = (e) => + @scrollView.on 'mousedown', (e) => clickCount = e.originalEvent.detail - screenPosition = @screenPositionFromMouseEvent(e) if clickCount == 1 if e.metaKey @@ -857,8 +856,6 @@ class Editor extends View @selectOnMousemoveUntilMouseup() unless e.ctrlKey or e.originalEvent.which > 1 - @renderedLines.on 'mousedown', onMouseDown - @on "textInput", (e) => @insertText(e.originalEvent.data) false