From 175d058ee39e8383c42cbf243f78511f5bd8dbc7 Mon Sep 17 00:00:00 2001 From: Kevin Azzam Date: Fri, 27 Mar 2015 22:39:35 +0100 Subject: [PATCH] Implemented middle click to jump-to-location --- lib/minimap-element.coffee | 24 ++++++++++++++--- spec/helpers/events.coffee | 8 +++--- spec/minimap-element-spec.coffee | 46 ++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 7 deletions(-) diff --git a/lib/minimap-element.coffee b/lib/minimap-element.coffee index c9c400bd..7611171a 100644 --- a/lib/minimap-element.coffee +++ b/lib/minimap-element.coffee @@ -450,9 +450,14 @@ class MinimapElement extends HTMLElement # {MinimapElement} canvas. # # event - The {Event} object. - mousePressedOverCanvas: ({which, pageY, target}) -> - return if which isnt 1 - + mousePressedOverCanvas: (e) -> + if e.which is 1 + @leftMousePressedOverCanvas(e) + else if e.which is 2 + @middleMousePressedOverCanvas(e) + else return + + leftMousePressedOverCanvas: ({pageY, target}) -> y = pageY - target.getBoundingClientRect().top row = Math.floor(y / @minimap.getLineHeight()) + @minimap.getFirstVisibleScreenRow() @@ -469,6 +474,16 @@ class MinimapElement extends HTMLElement else textEditor.setScrollTop(scrollTop) + middleMousePressedOverCanvas: ({pageY}) -> + {top: offsetTop} = @getBoundingClientRect() + y = pageY - offsetTop - @minimap.getTextEditorScaledHeight()/2 + + ratio = y / + (@minimap.getVisibleHeight() - @minimap.getTextEditorScaledHeight()) + + @minimap.textEditor.setScrollTop( + ratio * @minimap.getTextEditorMaxScrollTop()) + # Internal: A method that relays the `mousewheel` events received by # the {MinimapElement} to the {TextEditorElement}. # @@ -491,6 +506,9 @@ class MinimapElement extends HTMLElement # # event - The {Event} object. startDrag: ({which, pageY}) -> + if which is 2 + @mousePressedOverCanvas({which, pageY}) + return if which isnt 1 {top} = @visibleArea.getBoundingClientRect() {top: offsetTop} = @getBoundingClientRect() diff --git a/spec/helpers/events.coffee b/spec/helpers/events.coffee index 5f425331..61d46416 100644 --- a/spec/helpers/events.coffee +++ b/spec/helpers/events.coffee @@ -14,8 +14,7 @@ mouseEvent = (type, properties) -> shiftKey: false metaKey: false button: 0 - relatedTarget: `undefined` - which: 1 + relatedTarget: undefined } properties[k] = v for k,v of defaults when not properties[k]? @@ -29,14 +28,15 @@ objectCenterCoordinates = (obj) -> module.exports = {objectCenterCoordinates, mouseEvent} ['mousedown', 'mousemove', 'mouseup', 'click'].forEach (key) -> - module.exports[key] = (obj, {x, y, cx, cy, which}={}) -> + module.exports[key] = (obj, {x, y, cx, cy, btn} = {}) -> {x,y} = objectCenterCoordinates(obj) unless x? and y? unless cx? and cy? cx = x cy = y - obj.dispatchEvent(mouseEvent key, {pageX: x, pageY: y, clientX: cx, clientY: cy, which}) + obj.dispatchEvent(mouseEvent key, { + pageX: x, pageY: y, clientX: cx, clientY: cy, button: btn}) module.exports.mousewheel = (obj, deltaX=0, deltaY=0) -> obj.dispatchEvent(mouseEvent 'mousewheel', {deltaX, deltaY}) diff --git a/spec/minimap-element-spec.coffee b/spec/minimap-element-spec.coffee index 497270d6..51fb6750 100644 --- a/spec/minimap-element-spec.coffee +++ b/spec/minimap-element-spec.coffee @@ -305,6 +305,52 @@ describe 'MinimapElement', -> it 'relays the events to the editor view', -> expect(editorElement.component.presenter.setScrollTop).toHaveBeenCalled() + describe 'middle clicking the minimap', -> + [canvas, visibleArea, originalTop, originalLeft, maxScroll] = [] + + beforeEach -> + canvas = minimapElement.canvas + visibleArea = minimapElement.visibleArea + {top, left} = visibleArea.getBoundingClientRect() + [originalTop, originalLeft] = [top, left] + maxScroll = minimap.getTextEditorMaxScrollTop() + + it 'scrolls to the top using the middle mouse button', -> + mousedown(canvas, x: originalLeft + 1, y: 0, btn: 1) + expect(editor.getScrollTop()).toEqual(0) + + describe 'scrolling to the middle using the middle mouse button', -> + canvasMidY = undefined + + beforeEach -> + editorMidY = editor.getHeight() / 2.0 + {top, height} = canvas.getBoundingClientRect() + canvasMidY = top + (height / 2.0) + actualMidY = Math.min(canvasMidY, editorMidY) + mousedown(canvas, x: originalLeft + 1, y: actualMidY, btn: 1) + + it 'scrolls the editor to the middle', -> + middleScrollTop = Math.round((maxScroll) / 2.0) + expect(editor.getScrollTop()).toEqual(middleScrollTop) + + it 'updates the visible area to be centered', -> + nextAnimationFrame() + {top, height} = visibleArea.getBoundingClientRect() + visibleCenterY = top + (height / 2) + expect(visibleCenterY).toBeCloseTo(canvasMidY, 0) + + it 'scrolls the editor to an arbitrary location', -> + scrollTo = 100 # pixels + scrollRatio = (scrollTo - minimap.getTextEditorScaledHeight()/2) / + (minimap.getVisibleHeight() - minimap.getTextEditorScaledHeight()) + scrollRatio = Math.max(0, scrollRatio) + scrollRatio = Math.min(1, scrollRatio) + + mousedown(canvas, x: originalLeft + 1, y: scrollTo, btn: 1) + + expectedScroll = maxScroll * scrollRatio + expect(editor.getScrollTop()).toBeCloseTo(expectedScroll, 0) + describe 'pressing the mouse on the minimap canvas (without scroll animation)', -> beforeEach -> t = 0