diff --git a/spec/text-editor-component-spec.js b/spec/text-editor-component-spec.js index 0f7164b9b..0588aafa0 100644 --- a/spec/text-editor-component-spec.js +++ b/spec/text-editor-component-spec.js @@ -842,6 +842,126 @@ describe('TextEditorComponent', () => { }) }) + describe('scrolling via the mouse wheel', () => { + it('scrolls vertically when deltaY is not 0', () => { + const mouseWheelScrollSensitivity = 0.4 + const {component, editor} = buildComponent({height: 50, mouseWheelScrollSensitivity}) + + { + const expectedScrollTop = 20 * mouseWheelScrollSensitivity + component.didMouseWheel({deltaX: 0, deltaY: 20}) + expect(component.getScrollTop()).toBe(expectedScrollTop) + expect(component.refs.content.style.transform).toBe(`translate(0px, -${expectedScrollTop}px)`) + } + + { + const expectedScrollTop = component.getScrollTop() - (10 * mouseWheelScrollSensitivity) + component.didMouseWheel({deltaX: 0, deltaY: -10}) + expect(component.getScrollTop()).toBe(expectedScrollTop) + expect(component.refs.content.style.transform).toBe(`translate(0px, -${expectedScrollTop}px)`) + } + }) + + it('scrolls horizontally when deltaX is not 0', () => { + const mouseWheelScrollSensitivity = 0.4 + const {component, editor} = buildComponent({width: 50, mouseWheelScrollSensitivity}) + + { + const expectedScrollLeft = 20 * mouseWheelScrollSensitivity + component.didMouseWheel({deltaX: 20, deltaY: 0}) + expect(component.getScrollLeft()).toBe(expectedScrollLeft) + expect(component.refs.content.style.transform).toBe(`translate(-${expectedScrollLeft}px, 0px)`) + } + + { + const expectedScrollLeft = component.getScrollLeft() - (10 * mouseWheelScrollSensitivity) + component.didMouseWheel({deltaX: -10, deltaY: 0}) + expect(component.getScrollLeft()).toBe(expectedScrollLeft) + expect(component.refs.content.style.transform).toBe(`translate(-${expectedScrollLeft}px, 0px)`) + } + }) + + it('inverts deltaX and deltaY when holding shift on Windows and Linux', async () => { + const mouseWheelScrollSensitivity = 0.4 + const {component, editor} = buildComponent({height: 50, width: 50, mouseWheelScrollSensitivity}) + + component.props.platform = 'linux' + { + const expectedScrollTop = 20 * mouseWheelScrollSensitivity + component.didMouseWheel({deltaX: 0, deltaY: 20}) + expect(component.getScrollTop()).toBe(expectedScrollTop) + expect(component.refs.content.style.transform).toBe(`translate(0px, -${expectedScrollTop}px)`) + await setScrollTop(component, 0) + } + + { + const expectedScrollLeft = 20 * mouseWheelScrollSensitivity + component.didMouseWheel({deltaX: 0, deltaY: 20, shiftKey: true}) + expect(component.getScrollLeft()).toBe(expectedScrollLeft) + expect(component.refs.content.style.transform).toBe(`translate(-${expectedScrollLeft}px, 0px)`) + await setScrollLeft(component, 0) + } + + { + const expectedScrollTop = 20 * mouseWheelScrollSensitivity + component.didMouseWheel({deltaX: 20, deltaY: 0, shiftKey: true}) + expect(component.getScrollTop()).toBe(expectedScrollTop) + expect(component.refs.content.style.transform).toBe(`translate(0px, -${expectedScrollTop}px)`) + await setScrollTop(component, 0) + } + + component.props.platform = 'win32' + { + const expectedScrollTop = 20 * mouseWheelScrollSensitivity + component.didMouseWheel({deltaX: 0, deltaY: 20}) + expect(component.getScrollTop()).toBe(expectedScrollTop) + expect(component.refs.content.style.transform).toBe(`translate(0px, -${expectedScrollTop}px)`) + await setScrollTop(component, 0) + } + + { + const expectedScrollLeft = 20 * mouseWheelScrollSensitivity + component.didMouseWheel({deltaX: 0, deltaY: 20, shiftKey: true}) + expect(component.getScrollLeft()).toBe(expectedScrollLeft) + expect(component.refs.content.style.transform).toBe(`translate(-${expectedScrollLeft}px, 0px)`) + await setScrollLeft(component, 0) + } + + { + const expectedScrollTop = 20 * mouseWheelScrollSensitivity + component.didMouseWheel({deltaX: 20, deltaY: 0, shiftKey: true}) + expect(component.getScrollTop()).toBe(expectedScrollTop) + expect(component.refs.content.style.transform).toBe(`translate(0px, -${expectedScrollTop}px)`) + await setScrollTop(component, 0) + } + + component.props.platform = 'darwin' + { + const expectedScrollTop = 20 * mouseWheelScrollSensitivity + component.didMouseWheel({deltaX: 0, deltaY: 20}) + expect(component.getScrollTop()).toBe(expectedScrollTop) + expect(component.refs.content.style.transform).toBe(`translate(0px, -${expectedScrollTop}px)`) + await setScrollTop(component, 0) + } + + { + const expectedScrollTop = 20 * mouseWheelScrollSensitivity + component.didMouseWheel({deltaX: 0, deltaY: 20, shiftKey: true}) + expect(component.getScrollTop()).toBe(expectedScrollTop) + expect(component.refs.content.style.transform).toBe(`translate(0px, -${expectedScrollTop}px)`) + await setScrollTop(component, 0) + } + + { + const expectedScrollLeft = 20 * mouseWheelScrollSensitivity + component.didMouseWheel({deltaX: 20, deltaY: 0, shiftKey: true}) + expect(component.getScrollLeft()).toBe(expectedScrollLeft) + expect(component.refs.content.style.transform).toBe(`translate(-${expectedScrollLeft}px, 0px)`) + await setScrollLeft(component, 0) + } + }) + }) + describe('line and line number decorations', () => { it('adds decoration classes on screen lines spanned by decorated markers', async () => { const {component, element, editor} = buildComponent({width: 435, attach: false}) @@ -2974,7 +3094,8 @@ function buildComponent (params = {}) { model: editor, rowsPerTile: params.rowsPerTile, updatedSynchronously: false, - platform: params.platform + platform: params.platform, + mouseWheelScrollSensitivity: params.mouseWheelScrollSensitivity }) const {element} = component if (!editor.getAutoHeight()) { diff --git a/src/text-editor-component.js b/src/text-editor-component.js index b175a407d..d13259b96 100644 --- a/src/text-editor-component.js +++ b/src/text-editor-component.js @@ -19,7 +19,6 @@ const KOREAN_CHARACTER = '세' const NBSP_CHARACTER = '\u00a0' const ZERO_WIDTH_NBSP_CHARACTER = '\ufeff' const MOUSE_DRAG_AUTOSCROLL_MARGIN = 40 -const MOUSE_WHEEL_SCROLL_SENSITIVITY = 0.8 const CURSOR_BLINK_RESUME_DELAY = 300 const CURSOR_BLINK_PERIOD = 800 @@ -1361,9 +1360,17 @@ class TextEditorComponent { } didMouseWheel (event) { + const scrollSensitivity = this.props.mouseWheelScrollSensitivity || 0.8 + let {deltaX, deltaY} = event - deltaX = deltaX * MOUSE_WHEEL_SCROLL_SENSITIVITY - deltaY = deltaY * MOUSE_WHEEL_SCROLL_SENSITIVITY + deltaX = deltaX * scrollSensitivity + deltaY = deltaY * scrollSensitivity + + if (this.getPlatform() !== 'darwin' && event.shiftKey) { + let temp = deltaX + deltaX = deltaY + deltaY = temp + } const scrollPositionChanged = this.setScrollLeft(this.getScrollLeft() + deltaX) || @@ -1514,12 +1521,12 @@ class TextEditorComponent { } didMouseDownOnContent (event) { - const {model, platform} = this.props + const {model} = this.props const {target, button, detail, ctrlKey, shiftKey, metaKey} = event // Only handle mousedown events for left mouse button (or the middle mouse // button on Linux where it pastes the selection clipboard). - if (!(button === 0 || (platform === 'linux' && button === 1))) return + if (!(button === 0 || (this.getPlatform() === 'linux' && button === 1))) return const screenPosition = this.screenPositionForMouseEvent(event) @@ -1530,14 +1537,14 @@ class TextEditorComponent { } // Handle middle mouse button only on Linux (paste clipboard) - if (platform === 'linux' && button === 1) { + if (this.getPlatform() === 'linux' && button === 1) { const selection = clipboard.readText('selection') model.setCursorScreenPosition(screenPosition, {autoscroll: false}) model.insertText(selection) return } - const addOrRemoveSelection = metaKey || (ctrlKey && platform !== 'darwin') + const addOrRemoveSelection = metaKey || (ctrlKey && this.getPlatform() !== 'darwin') switch (detail) { case 1: @@ -1582,7 +1589,7 @@ class TextEditorComponent { } didMouseDownOnLineNumberGutter (event) { - const {model, platform} = this.props + const {model} = this.props const {target, button, ctrlKey, shiftKey, metaKey} = event // Only handle mousedown events for left mouse button @@ -1596,7 +1603,7 @@ class TextEditorComponent { return } - const addOrRemoveSelection = metaKey || (ctrlKey && platform !== 'darwin') + const addOrRemoveSelection = metaKey || (ctrlKey && this.getPlatform() !== 'darwin') const endBufferRow = model.bufferPositionForScreenPosition([clickedScreenRow, Infinity]).row const clickedLineBufferRange = Range(Point(startBufferRow, 0), Point(endBufferRow + 1, 0)) @@ -2181,9 +2188,9 @@ class TextEditorComponent { } didChangeSelectionRange () { - const {model, platform} = this.props + const {model} = this.props - if (platform === 'linux') { + if (this.getPlatform() === 'linux') { if (this.selectionClipboardImmediateId) { clearImmediate(this.selectionClipboardImmediateId) } @@ -2568,6 +2575,10 @@ class TextEditorComponent { isInputEnabled (inputEnabled) { return this.props.inputEnabled != null ? this.props.inputEnabled : true } + + getPlatform () { + return this.props.platform || process.platform + } } class DummyScrollbarComponent {