Skip to content

Commit

Permalink
Merge pull request #6147 from jonfunkhouser/bug/5219
Browse files Browse the repository at this point in the history
disable polar rotation drag when dragmode = false
  • Loading branch information
archmoj committed May 9, 2022
2 parents 8c63407 + 70cb931 commit f649320
Show file tree
Hide file tree
Showing 4 changed files with 297 additions and 10 deletions.
2 changes: 2 additions & 0 deletions draftlogs/6147_fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Fix for disabling polar rotation when `dragmode` is set to false [[#6147](https://github.com/plotly/plotly.js/pull/6147)],
with thanks to @jonfunkhouser for the contribution!
4 changes: 3 additions & 1 deletion src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2171,7 +2171,9 @@ function _relayout(gd, aobj) {
if(parentFull.autorange) flags.calc = true;
else flags.plot = true;
} else {
if((fullLayout._has('scatter-like') && fullLayout._has('regl')) &&
if(ai === 'dragmode' && ((vi === false && vOld !== false) || (vi !== false && vOld === false))) {
flags.plot = true;
} else if((fullLayout._has('scatter-like') && fullLayout._has('regl')) &&
(ai === 'dragmode' &&
(vi === 'lasso' || vi === 'select') &&
!(vOld === 'lasso' || vOld === 'select'))
Expand Down
19 changes: 13 additions & 6 deletions src/plots/polar/polar.js
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,7 @@ proto.updateHoverAndMainDrag = function(fullLayout) {
var scaleX;
var scaleY;

var mainDrag = dragBox.makeDragger(layers, 'path', 'maindrag', 'crosshair');
var mainDrag = dragBox.makeDragger(layers, 'path', 'maindrag', fullLayout.dragmode === false ? 'none' : 'crosshair');

d3.select(mainDrag)
.attr('d', _this.pathSubplot())
Expand Down Expand Up @@ -1150,6 +1150,9 @@ proto.updateRadialDrag = function(fullLayout, polarLayout, rngIndex) {

var radialDrag = dragBox.makeRectDragger(layers, className, 'crosshair', -bl2, -bl2, bl, bl);
var dragOpts = {element: radialDrag, gd: gd};
if(fullLayout.dragmode === false) {
dragOpts.dragmode = false;
}

updateElement(d3.select(radialDrag), radialAxis.visible && innerRadius < radius, {
transform: strTranslate(tx, ty)
Expand Down Expand Up @@ -1292,13 +1295,17 @@ proto.updateAngularDrag = function(fullLayout) {
var cyy = _this.cyy;
var dbs = constants.angularDragBoxSize;

var angularDrag = dragBox.makeDragger(layers, 'path', 'angulardrag', 'move');
var angularDrag = dragBox.makeDragger(layers, 'path', 'angulardrag', fullLayout.dragmode === false ? 'none' : 'move');
var dragOpts = {element: angularDrag, gd: gd};

d3.select(angularDrag)
.attr('d', _this.pathAnnulus(radius, radius + dbs))
.attr('transform', strTranslate(cx, cy))
.call(setCursor, 'move');
if(fullLayout.dragmode === false) {
dragOpts.dragmode = false;
} else {
d3.select(angularDrag)
.attr('d', _this.pathAnnulus(radius, radius + dbs))
.attr('transform', strTranslate(cx, cy))
.call(setCursor, 'move');
}

function xy2a(x, y) {
return Math.atan2(cyy + dbs - y, x - cxx - dbs);
Expand Down
282 changes: 279 additions & 3 deletions test/jasmine/tests/polar_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -961,7 +961,7 @@ describe('Test polar interactions:', function() {
.then(done, done.fail);
});

it('should response to drag interactions on radial drag area', function(done) {
it('should respond to drag interactions on radial drag area', function(done) {
var fig = Lib.extendDeep({}, require('@mocks/polar_scatter.json'));

// to avoid dragging on hover labels
Expand Down Expand Up @@ -1044,7 +1044,7 @@ describe('Test polar interactions:', function() {
.then(done, done.fail);
});

it('should response to drag interactions on inner radial drag area', function(done) {
it('should respond to drag interactions on inner radial drag area', function(done) {
var fig = Lib.extendDeep({}, require('@mocks/polar_scatter.json'));
fig.layout.polar.hole = 0.2;
// to avoid dragging on hover labels
Expand Down Expand Up @@ -1082,7 +1082,7 @@ describe('Test polar interactions:', function() {
.then(done, done.fail);
});

it('should response to drag interactions on angular drag area', function(done) {
it('should respond to drag interactions on angular drag area', function(done) {
var fig = Lib.extendDeep({}, require('@mocks/polar_scatter.json'));

// to avoid dragging on hover labels
Expand Down Expand Up @@ -1146,6 +1146,282 @@ describe('Test polar interactions:', function() {
.then(done, done.fail);
});

describe('dragmode === false', function() {
it('should not respond to drag interactions on plot area when dragmode === false', function(done) {
var fig = Lib.extendDeep({}, require('@mocks/polar_scatter.json'));
// adjust margins so that middle of plot area is at 300x300
// with its middle at [200,200]
fig.layout.width = 400;
fig.layout.height = 400;
fig.layout.margin = {l: 50, t: 50, b: 50, r: 50};

var mid = [200, 200];
var resetNumber = 0;

function _drag(p0, dp) {
var node = d3Select('.polar > .draglayer > .maindrag').node();
return drag({node: node, dpos: dp, pos0: p0});
}

function _assertRange(rng, msg) {
expect(gd._fullLayout.polar.radialaxis.range).toBeCloseToArray(rng, 1, msg);
}

function _assertBase(extra) {
var msg = 'base range' + (extra ? ' ' + extra : '');
_assertRange([0, 11.1], msg);
}

function _reset() {
resetNumber++;

var extra = '(reset ' + resetNumber + ')';
_assertBase(extra);
expect(eventCnts.plotly_doubleclick).toBe(0, 'doubleclick event #' + extra);
}

_plot(fig)
.then(_assertBase)
.then(function() { return Plotly.relayout(gd, 'dragmode', false); })
.then(function() { return _drag(mid, [50, 50]); })
.then(function() {
_assertBase('from center move toward bottom-right');
})
.then(delay(20))
.then(function() { return _doubleClick(mid); })
.then(delay(20))
.then(_reset)
.then(function() { return _drag(mid, [-50, -50]); })
.then(function() {
_assertBase('from center move toward top-left');
})
.then(delay(20))
.then(function() { return _doubleClick(mid); })
.then(delay(20))
.then(_reset)
.then(function() { return _drag([mid[0] + 30, mid[0] - 30], [50, -50]); })
.then(function() {
_assertBase('from quadrant #1 move top-right');
})
.then(delay(20))
.then(function() { return _doubleClick(mid); })
.then(delay(20))
.then(_reset)
.then(function() { return _drag([345, 200], [-50, 0]); })
.then(function() {
_assertBase('from right edge move left');
})
.then(delay(20))
.then(function() { return _doubleClick(mid); })
.then(delay(20))
.then(_reset)
.then(function() { return _drag(mid, [10, 10]);})
.then(function() { _assertBase('from center to not far enough'); })
.then(function() { return _drag([mid[0] + 30, mid[0] - 30], [-10, 0]);})
.then(function() { _assertBase('from quadrant #1 to not far enough'); })
.then(function() { return _drag([345, 200], [-10, 0]);})
.then(function() { _assertBase('from right edge to not far enough'); })
.then(function() {
expect(eventCnts.plotly_relayout)
.toBe(1, 'no new relayout events after *not far enough* cases');
})
.then(delay(20))
.then(function() { return _doubleClick(mid); })
.then(delay(20))
.then(_reset)
.then(function() { return Plotly.relayout(gd, 'polar.hole', 0.2); })
.then(function() { return _drag([mid[0] + 30, mid[0] - 30], [50, -50]); })
.then(function() {
_assertRange([0, 11.4], 'with polar.hole>0, from quadrant #1 move top-right');
})
.then(done, done.fail);
});

it('should not respond to drag interactions on radial drag area when dragmode === false', function(done) {
var fig = Lib.extendDeep({}, require('@mocks/polar_scatter.json'));
// adjust margins so that middle of plot area is at 300x300
// with its middle at [200,200]
fig.layout.width = 400;
fig.layout.height = 400;
fig.layout.margin = {l: 50, t: 50, b: 50, r: 50};

var dragPos0 = [375, 200];
var resetNumber = 0;

// use 'special' drag method - as we need two mousemove events
// to activate the radial drag mode
function _drag(p0, dp) {
var node = d3Select('.polar > .draglayer > .radialdrag').node();
return drag({node: node, dpos: dp, pos0: p0, nsteps: 2});
}

function _assert(rng, angle, evtRng1, evtAngle, msg) {
expect(gd._fullLayout.polar.radialaxis.range)
.toBeCloseToArray(rng, 1, msg + ' - range');
expect(gd._fullLayout.polar.radialaxis.angle)
.toBeCloseTo(angle, 1, msg + ' - angle');

if(evtRng1 !== null) {
expect(eventData['polar.radialaxis.range[1]'])
.toBeCloseTo(evtRng1, 1, msg + ' - range[1] event data');
}
if(evtAngle !== null) {
expect(eventData['polar.radialaxis.angle'])
.toBeCloseTo(evtAngle, 1, msg + ' - angle event data');
}
}

function _assertBase(extra) {
extra = extra ? ' ' + extra : '';
_assert([0, 11.1], 0, null, null, 'base' + extra);
}

function _reset() {
return delay(100)()
.then(function() { return _doubleClick([200, 200]); })
.then(function() {
resetNumber++;

var extra = '(reset ' + resetNumber + ')';
_assertBase(extra);
expect(eventCnts.plotly_doubleclick).toBe(0, 'doubleclick event #' + extra);
});
}

_plot(fig)
.then(_assertBase)
.then(function() { return Plotly.relayout(gd, 'dragmode', false); })
.then(function() { return _drag(dragPos0, [-50, 0]); })
.then(function() {
_assertBase('move inward');
})
.then(_reset)
.then(function() { return _drag(dragPos0, [50, 0]); })
.then(function() {
_assertBase('move outward');
})
.then(_reset)
.then(function() { return _drag(dragPos0, [0, -50]); })
.then(function() {
_assertBase('move counterclockwise');
})
.then(_reset)
.then(function() { return _drag(dragPos0, [0, 50]); })
.then(function() {
_assertBase('move clockwise');
})
.then(_reset)
.then(function() {
expect(eventCnts.plotly_relayout).toBe(1, 'total # of relayout events');
})
.then(done, done.fail);
});

it('should not respond to drag interactions on inner radial drag area when dragmode === false', function(done) {
var fig = Lib.extendDeep({}, require('@mocks/polar_scatter.json'));
fig.layout.polar.hole = 0.2;
// adjust margins so that middle of plot area is at 300x300
// with its middle at [200,200]
fig.layout.width = 400;
fig.layout.height = 400;
fig.layout.margin = {l: 50, t: 50, b: 50, r: 50};

var dragPos0 = [200, 200];

// use 'special' drag method - as we need two mousemove events
// to activate the radial drag mode
function _drag(p0, dp) {
var node = d3Select('.polar > .draglayer > .radialdrag-inner').node();
return drag({node: node, dpos: dp, pos0: p0, nsteps: 2});
}

function _assert(rng, msg) {
expect(gd._fullLayout.polar.radialaxis.range)
.toBeCloseToArray(rng, 1, msg + ' - range');
}

function _assertBase(extra) {
extra = extra ? ' ' + extra : '';
_assert([0, 11.4], 'base' + extra);
}

_plot(fig)
.then(_assertBase)
.then(function() { return Plotly.relayout(gd, 'dragmode', false); })
.then(function() { return _drag(dragPos0, [-50, 0]); })
.then(function() {
_assertBase('move inward');
})
.then(function() { return Plotly.relayout(gd, 'polar.radialaxis.autorange', true); })
.then(function() { return _drag(dragPos0, [50, 0]); })
.then(function() {
_assertBase('move outward');
})
.then(done, done.fail);
});

it('should not respond to drag interactions on angular drag area when dragmode === false', function(done) {
var fig = Lib.extendDeep({}, require('@mocks/polar_scatter.json'));
// adjust margins so that middle of plot area is at 300x300
// with its middle at [200,200]
fig.layout.width = 400;
fig.layout.height = 400;
fig.layout.margin = {l: 50, t: 50, b: 50, r: 50};

var dragPos0 = [350, 150];
var resetNumber = 0;

function _drag(p0, dp) {
var node = d3Select('.polar > .draglayer > .angulardrag').node();
return drag({node: node, dpos: dp, pos0: p0});
}

function _assert(rot, msg, noEvent) {
expect(gd._fullLayout.polar.angularaxis.rotation)
.toBeCloseTo(rot, 1, msg + ' - rotation');
if(!noEvent) {
expect(eventData['polar.angularaxis.rotation'])
.toBeCloseTo(rot, 1, msg + ' - rotation event data');
}
}

function _assertBase(extra) {
extra = extra ? ' ' + extra : '';
_assert(0, 'base' + extra, true);
}

function _reset() {
return delay(100)()
.then(function() { return _doubleClick([200, 200]); })
.then(function() {
resetNumber++;

var extra = '(reset ' + resetNumber + ')';
_assertBase(extra);
expect(eventCnts.plotly_doubleclick).toBe(0, 'doubleclick event #' + extra);
});
}

_plot(fig)
.then(_assertBase)
.then(function() { return Plotly.relayout(gd, 'dragmode', false); })
.then(function() { return _drag(dragPos0, [-20, -20]); })
.then(function() {
_assertBase('move counterclockwise');
})
.then(_reset)
.then(function() { return _drag(dragPos0, [20, 20]); })
.then(function() {
_assertBase('move clockwise');
})
.then(_reset)
.then(function() {
expect(eventCnts.plotly_relayout).toBe(1, 'total # of relayout events');
})
.then(done, done.fail);
});
});

describe('should update scene during drag interactions on radial and angular drag area', function() {
var objs = ['scatter2d', 'line2d'];
var scene, gl, nTraces;
Expand Down

0 comments on commit f649320

Please sign in to comment.