-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Configurable select direction #2506
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Configurable select direction #2506
Conversation
description: [ | ||
'When "dragmode" is set to "select", this limits the selection of the drag to', | ||
'horizontal, vertical or diagonal. "h" only allows horizontal selection,', | ||
'"v" only vertical, "d" only diagonal and "any" sets no limit.' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, I like 'd'
, I guess what it allows that 'any'
doesn't is selecting regions that are very narrow in height or width, which would otherwise devolve to pure horizontal or vertical selections. Cool.
src/components/fx/layout_defaults.js
Outdated
@@ -17,6 +17,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { | |||
} | |||
|
|||
coerce('dragmode'); | |||
coerce('selectdirection', 'any'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the attribute has dflt: 'any'
already, you do not need to include it here.
"yaxis2": { "domain": [0.51, 1] }, | ||
"showlegend": false, | ||
"dragmode": "select", | ||
"selectdirection": "any" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to make image test mocks for selectdirection
, since it has no effect on the static images. For the jasmine tests, if you don't like the mock (14) that we use in the neighboring tests, you can use any other predefined mock, or just make a new plot explicitly in the test, something like:
Plotly.newPlot(gd, [
{x: [1,1,1,1,1,2,2,2,3,3], type: 'histogram'},
{x: [1,2,3], y:[-1,-2,-3], type: 'bar'}
], {
showlegend: false,
dragmode: 'select'
})
.then(function() {
expect(gd.fullLayout.selectdirection).toBe('any');
// do a drag and check that the selection is correct for the default `selectdirection`
return Plotly.relayout(gd, {selectdirection: 'h'});
})
.then(function() {
// do probably the SAME drag and check that the selection is correct for the `selectdirection='h'`
return Plotly.relayout(gd, {selectdirection: 'v'});
})
.then(function() {
// ...
})
.catch(fail) // hmm, we should change the name of this import to failTest, since fail is already a jasmine global, for sync failure, we're overriding it here with our async version (we've already done this in other places)
.then(done);
While it's nice to be able to write a test where you've pre-calculated what the outcome should be, it's not always necessary: as long as you can demonstrate a difference between the different modes, you can just write tests, watch them fail when you run them, and change them so they pass. But if you do want to do the calculation yourself, I've had good luck setting explicit |
@alexcjohnson can you have a look at this commit to see if I'm on the right track? |
test/jasmine/tests/select_test.js
Outdated
|
||
return Plotly.relayout(gd, {selectdirection: 'h'}); | ||
}) | ||
.then(function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, this looks good! Make sure you keep chaining the async events - your selectedPromise.then...
is not being waited for by the following code so it's not entirely clear what sequence things will happen in. Try something like:
Plotly.newPlot(...)
.then(function() {
resetEvents(gd);
drag(selectPath);
return selectedPromise;
})
.then(function() {
expect(selectedData.points.length).toBe(1);
// etc
return Plotly.relayout(...);
})
Here's a tool I used to help create the tests: https://jsfiddle.net/c0ojh6vq/8/ (just shows you the mouse hover position on the drag layer). |
The CI test appears to be failing on an unrelated part before the selectdirection tests ("Test polar interactions: should response to drag interactions on plot area FAILED"), are these tests known to fail from time to time? |
@alexcjohnson Can you have a look at this? Can't reproduce the test failures locally. |
Oh sorry about letting this one slip through last week - thanks for pinging me again. Yes, the test failure is unrelated, we should probably mark that test as Anyway I could rerun it for you but it still looks like the promise chain in your test is branched - see #2506 (comment) - can you rearrange so every |
@GlennMatthys I'll finish this up, so it can go out with v1.36 this afternoon. |
- flatten the promise chain - simplify the test plot so I can better understand what *should* happen
@etpinard care to take a quick look? |
I wanted to finish this up but I'm struggling to get the tests to succeed. How do you calculate the select path? To which element are these coordinates relative to? Is there some offset that needs to be taken into account? |
src/components/fx/layout_defaults.js
Outdated
@@ -17,6 +17,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { | |||
} | |||
|
|||
coerce('dragmode'); | |||
coerce('selectdirection'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only has an effect for dragmode: 'select'
, correct? So should this be:
var dragMode = coerce('dragmode');
if(dragMode === 'select') {
coerce('selectdirection')
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep -> conditional coerce 9dd166c
@GlennMatthys I think it's all set now, check out 6d4a4f8 But for reference, if you're contributing more in the future, it's relative to the corner of the plot, including the margins. That's why in that commit you can see I set the margins, size, and axis ranges explicitly so I know x is 100px->0, 300px->4, and y is the opposite 100px->4, 300px-> 0 |
src/plots/cartesian/select.js
Outdated
@@ -192,6 +192,8 @@ function prepSelect(e, startX, startY, dragOptions, mode) { | |||
} | |||
} | |||
|
|||
var direction = fullLayout.selectdirection; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
direction
doesn't get used in the outer scope. Could be move that var direction
into the moveFn
scope below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good call -> pushed to inner scope 9dd166c
Not sure if CI is extra-flaky today or if splom and other new features are causing it to bog down... but anyway I moved those new shape tests to |
Nicely done 💃 |
Can the coordinate system for selections be documented somewhere, perhaps in the contributing guide? This should help newcomers orient themselves, plus the tips like fixing the margins and axis ranges to produce a much more reliable canvas to do select tests on. Some visual representation would be nice too: |
That's a good idea - @etpinard where would be the right place for this? I like your diagram. Note that [175, 175] and [225, 225] go one (data) unit down and right of where you have them, ie 175 is actually where you've drawn 225. |
Made a new PR so this can be discussed more appropriately, also fixed the diagram. |
Proper implementation of #2495. This PR includes:
Also adds a "d" selectiondirection to only allow diagonal selects.
Working on writing a proper test for this functionality, I'm still figuring out how to do the necessary calculations.