From 8a57ba143d9eff2483322739cb2175c3286179fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Tue, 29 Nov 2016 15:02:57 -0500 Subject: [PATCH 1/3] add false value to scene.dragmode - to remove drag interactions from a given gl3d scene --- src/plots/gl3d/camera.js | 12 +++++++++--- src/plots/gl3d/layout/layout_attributes.js | 2 +- src/plots/gl3d/scene.js | 2 ++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/plots/gl3d/camera.js b/src/plots/gl3d/camera.js index 70f93ecb2e5..e97fc8b213a 100644 --- a/src/plots/gl3d/camera.js +++ b/src/plots/gl3d/camera.js @@ -181,9 +181,13 @@ function createCamera(element, options) { var lastX = 0, lastY = 0; mouseChange(element, function(buttons, x, y, mods) { - var rotate = camera.keyBindingMode === 'rotate'; - var pan = camera.keyBindingMode === 'pan'; - var zoom = camera.keyBindingMode === 'zoom'; + var keyBindingMode = camera.keyBindingMode; + + if(keyBindingMode === false) return; + + var rotate = keyBindingMode === 'rotate'; + var pan = keyBindingMode === 'pan'; + var zoom = keyBindingMode === 'zoom'; var ctrl = !!mods.control; var alt = !!mods.alt; @@ -226,6 +230,8 @@ function createCamera(element, options) { }); mouseWheel(element, function(dx, dy) { + if(camera.keyBindingMode === false) return; + var flipX = camera.flipX ? 1 : -1; var flipY = camera.flipY ? 1 : -1; var t = now(); diff --git a/src/plots/gl3d/layout/layout_attributes.js b/src/plots/gl3d/layout/layout_attributes.js index a708ea7f1e7..7b83424f1f7 100644 --- a/src/plots/gl3d/layout/layout_attributes.js +++ b/src/plots/gl3d/layout/layout_attributes.js @@ -142,7 +142,7 @@ module.exports = { dragmode: { valType: 'enumerated', role: 'info', - values: ['orbit', 'turntable', 'zoom', 'pan'], + values: ['orbit', 'turntable', 'zoom', 'pan', false], dflt: 'turntable', description: [ 'Determines the mode of drag interactions for this scene.' diff --git a/src/plots/gl3d/scene.js b/src/plots/gl3d/scene.js index f287a5c3aa9..fd921f99d6f 100644 --- a/src/plots/gl3d/scene.js +++ b/src/plots/gl3d/scene.js @@ -173,6 +173,8 @@ function initializeGLPlot(scene, fullLayout, canvas, gl) { } var relayoutCallback = function(scene) { + if(scene.fullSceneLayout.dragmode === false) return; + var update = {}; update[scene.id] = getLayoutCamera(scene.camera); scene.saveCamera(scene.graphDiv.layout); From b15a4c93a7d8cabf60a93999861028d251c7a35d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Mon, 13 Feb 2017 15:49:45 -0500 Subject: [PATCH 2/3] make dragmode -> scene.dragmode logic more robust --- src/plots/gl3d/layout/defaults.js | 11 +++-------- test/jasmine/tests/gl3dlayout_test.js | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/plots/gl3d/layout/defaults.js b/src/plots/gl3d/layout/defaults.js index 285da8b2920..1fafd4a49a4 100644 --- a/src/plots/gl3d/layout/defaults.js +++ b/src/plots/gl3d/layout/defaults.js @@ -9,6 +9,7 @@ 'use strict'; +var Lib = require('../../../lib'); var Color = require('../../../components/color'); var handleSubplotDefaults = require('../../subplot_defaults'); @@ -17,20 +18,14 @@ var supplyGl3dAxisLayoutDefaults = require('./axis_defaults'); module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - var hasNon3D = ( - layoutOut._has('cartesian') || - layoutOut._has('geo') || - layoutOut._has('gl2d') || - layoutOut._has('pie') || - layoutOut._has('ternary') - ); + var hasNon3D = layoutOut._basePlotModules.length > 1; // some layout-wide attribute are used in all scenes // if 3D is the only visible plot type function getDfltFromLayout(attr) { if(hasNon3D) return; - var isValid = layoutAttributes[attr].values.indexOf(layoutIn[attr]) !== -1; + var isValid = Lib.validate(layoutIn[attr], layoutAttributes[attr]); if(isValid) return layoutIn[attr]; } diff --git a/test/jasmine/tests/gl3dlayout_test.js b/test/jasmine/tests/gl3dlayout_test.js index f6e2fd24d07..31099fd7a46 100644 --- a/test/jasmine/tests/gl3dlayout_test.js +++ b/test/jasmine/tests/gl3dlayout_test.js @@ -1,5 +1,4 @@ var Gl3d = require('@src/plots/gl3d'); -var Plots = require('@src/plots/plots'); var tinycolor = require('tinycolor2'); var Color = require('@src/components/color'); @@ -14,9 +13,7 @@ describe('Test Gl3d layout defaults', function() { var supplyLayoutDefaults = Gl3d.supplyLayoutDefaults; beforeEach(function() { - layoutOut = { - _has: Plots._hasPlotType - }; + layoutOut = { _basePlotModules: ['gl3d'] }; // needs a scene-ref in a trace in order to be detected fullData = [ { type: 'scatter3d', scene: 'scene' }]; @@ -174,8 +171,13 @@ describe('Test Gl3d layout defaults', function() { expect(layoutOut.scene.dragmode) .toBe('orbit', 'to user layout val if valid and 3d only'); + layoutIn = { scene: {}, dragmode: 'invalid' }; + supplyLayoutDefaults(layoutIn, layoutOut, fullData); + expect(layoutOut.scene.dragmode) + .toBe('turntable', 'to turntable if invalid and 3d only'); + layoutIn = { scene: {}, dragmode: 'orbit' }; - layoutOut._basePlotModules = [{ name: 'cartesian' }]; + layoutOut._basePlotModules.push({ name: 'cartesian' }); supplyLayoutDefaults(layoutIn, layoutOut, fullData); expect(layoutOut.scene.dragmode) .toBe('turntable', 'to default if not 3d only'); @@ -202,8 +204,13 @@ describe('Test Gl3d layout defaults', function() { expect(layoutOut.scene.hovermode) .toBe(false, 'to user layout val if valid and 3d only'); + layoutIn = { scene: {}, hovermode: 'invalid' }; + supplyLayoutDefaults(layoutIn, layoutOut, fullData); + expect(layoutOut.scene.hovermode) + .toBe('closest', 'to closest if invalid and 3d only'); + layoutIn = { scene: {}, hovermode: false }; - layoutOut._basePlotModules = [{ name: 'cartesian' }]; + layoutOut._basePlotModules.push({ name: 'cartesian' }); supplyLayoutDefaults(layoutIn, layoutOut, fullData); expect(layoutOut.scene.hovermode) .toBe('closest', 'to default if not 3d only'); From 2e4f00122e9bb471e16aa9c0fce84eeab84b0438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Mon, 13 Feb 2017 17:47:17 -0500 Subject: [PATCH 3/3] improve 3d drag/scroll test + test `dragmode: false` --- test/jasmine/tests/gl_plot_interact_test.js | 89 +++++++++++++++------ 1 file changed, 66 insertions(+), 23 deletions(-) diff --git a/test/jasmine/tests/gl_plot_interact_test.js b/test/jasmine/tests/gl_plot_interact_test.js index 2a7960b93e3..38b3a821a9f 100644 --- a/test/jasmine/tests/gl_plot_interact_test.js +++ b/test/jasmine/tests/gl_plot_interact_test.js @@ -595,6 +595,23 @@ describe('Test gl plot interactions', function() { }); describe('drag and wheel interactions', function() { + + function scroll(target) { + return new Promise(function(resolve) { + target.dispatchEvent(new WheelEvent('wheel', {deltaY: 1})); + setTimeout(resolve, 0); + }); + } + + function drag(target) { + return new Promise(function(resolve) { + target.dispatchEvent(new MouseEvent('mousedown', {x: 0, y: 0})); + target.dispatchEvent(new MouseEvent('mousemove', { x: 100, y: 100})); + target.dispatchEvent(new MouseEvent('mouseup', { x: 100, y: 100})); + setTimeout(resolve, 0); + }); + } + it('should update the scene camera', function(done) { var sceneLayout = gd._fullLayout.scene, sceneLayout2 = gd._fullLayout.scene2, @@ -606,37 +623,63 @@ describe('Test gl plot interactions', function() { expect(sceneLayout2.camera.eye) .toEqual({x: 2.5, y: 2.5, z: 2.5}); - // Wheel scene 1 - sceneTarget.dispatchEvent(new WheelEvent('wheel', {deltaY: 1})); - - // Wheel scene 2 - sceneTarget2.dispatchEvent(new WheelEvent('wheel', {deltaY: 1})); - - setTimeout(function() { - - expect(relayoutCallback).toHaveBeenCalledTimes(2); - + scroll(sceneTarget).then(function() { + expect(relayoutCallback).toHaveBeenCalledTimes(1); relayoutCallback.calls.reset(); - // Drag scene 1 - sceneTarget.dispatchEvent(new MouseEvent('mousedown', {x: 0, y: 0})); - sceneTarget.dispatchEvent(new MouseEvent('mousemove', { x: 100, y: 100})); - sceneTarget.dispatchEvent(new MouseEvent('mouseup', { x: 100, y: 100})); + return scroll(sceneTarget2); + }) + .then(function() { + expect(relayoutCallback).toHaveBeenCalledTimes(1); + relayoutCallback.calls.reset(); - // Drag scene 2 - sceneTarget2.dispatchEvent(new MouseEvent('mousedown', {x: 0, y: 0 })); - sceneTarget2.dispatchEvent(new MouseEvent('mousemove', {x: 100, y: 100})); - sceneTarget2.dispatchEvent(new MouseEvent('mouseup', {x: 100, y: 100})); + return drag(sceneTarget2); + }) + .then(function() { + expect(relayoutCallback).toHaveBeenCalledTimes(1); + relayoutCallback.calls.reset(); - setTimeout(function() { + return drag(sceneTarget); + }) + .then(function() { + expect(relayoutCallback).toHaveBeenCalledTimes(1); + relayoutCallback.calls.reset(); - expect(relayoutCallback).toHaveBeenCalledTimes(2); + return Plotly.relayout(gd, { + 'scene.dragmode': false, + 'scene2.dragmode': false + }); + }) + .then(function() { + expect(relayoutCallback).toHaveBeenCalledTimes(1); + relayoutCallback.calls.reset(); - done(); + return drag(sceneTarget); + }) + .then(function() { + return drag(sceneTarget2); + }) + .then(function() { + expect(relayoutCallback).toHaveBeenCalledTimes(0); - }, MODEBAR_DELAY); + return Plotly.relayout(gd, { + 'scene.dragmode': 'orbit', + 'scene2.dragmode': 'turntable' + }); + }) + .then(function() { + expect(relayoutCallback).toHaveBeenCalledTimes(1); + relayoutCallback.calls.reset(); - }, MODEBAR_DELAY); + return drag(sceneTarget); + }) + .then(function() { + return drag(sceneTarget2); + }) + .then(function() { + expect(relayoutCallback).toHaveBeenCalledTimes(2); + }) + .then(done); }); }); });