Skip to content

Interactive span selector improvement #20113

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

Merged
merged 35 commits into from
Jun 30, 2021

Conversation

ericpre
Copy link
Member

@ericpre ericpre commented Apr 29, 2021

PR Summary

This PR updates the SpanSelector to make it consistent with RectangleSelector:

If you are happy with the changes, I will do the remaining doc, examples, etc updates.

PR Checklist

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (run flake8 on changed files to check).
  • New features are documented, with examples if plot related.
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).
  • Conforms to Matplotlib style conventions (install flake8-docstrings and run flake8 --docstring-convention=all).
  • New features have an entry in doc/users/next_whats_new/ (follow instructions in README.rst there).
  • API changes documented in doc/api/next_api_changes/ (follow instructions in README.rst there).

@anntzer
Copy link
Contributor

anntzer commented May 10, 2021

interactive differs from span_stays in that with span_stays it was possible to completely unset a previously set SpanSelector by clicking anywhere (effectively drawing a zero-sized selector), whereas this is now impossible(?) with interactive. Not vetoing the change, but I would be slightly annoyed, being used to the old semantics (well, I don't know how intuitive they were either)...
(I guess the old semantics are conflicting with drag_from_anywhere :/ but at least they should beep working when drag_from_anywhere = False (the default))

@ericpre
Copy link
Member Author

ericpre commented May 12, 2021

interactive differs from span_stays in that with span_stays it was possible to completely unset a previously set SpanSelector by clicking anywhere (effectively drawing a zero-sized selector), whereas this is now impossible(?) with interactive. Not vetoing the change, but I would be slightly annoyed, being used to the old semantics (well, I don't know how intuitive they were either)...
(I guess the old semantics are conflicting with drag_from_anywhere :/ but at least they should beep working when drag_from_anywhere = False (the default))

Thanks for the review! Indeed, this is a change in behaviour and the motivation for this really is to have the SpanSelector behaving consistently with other widgets where possible. The current inconsistency could be considered as a bug! ;)
My view on this is that consistency and improved code readability/easier maintenance are worth a (small?) change in behaviour!

@ericpre ericpre requested a review from anntzer May 12, 2021 19:27
@ericpre
Copy link
Member Author

ericpre commented May 13, 2021

interactive differs from span_stays in that with span_stays it was possible to completely unset a previously set SpanSelector by clicking anywhere (effectively drawing a zero-sized selector), whereas this is now impossible(?) with interactive. Not vetoing the change, but I would be slightly annoyed, being used to the old semantics (well, I don't know how intuitive they were either)...
(I guess the old semantics are conflicting with drag_from_anywhere :/ but at least they should beep working when drag_from_anywhere = False (the default))

Thanks for the review! Indeed, this is a change in behaviour and the motivation for this really is to have the SpanSelector behaving consistently with other widgets where possible. The current inconsistency could be considered as a bug! ;)
My view on this is that consistency and improved code readability/easier maintenance are worth a (small?) change in behaviour!

Actually, thinking a bit more about it, I would like to add a separate optional parameter to the SpanSelector (and RectangleSelector, etc) to ignore events outside the widgets and I would prefer to do this in a follow up PR, because there are already a lot of changes in this PR. What do you think?

@ericpre ericpre mentioned this pull request May 19, 2021
7 tasks
@ericpre ericpre force-pushed the interactive_span_selector branch from 7137b09 to c9efdfa Compare May 20, 2021 19:19
@ericpre
Copy link
Member Author

ericpre commented May 20, 2021

Rebase on master to check that #9660 is fixed with this PR and #20264 and it seems to be the case!

@jklymak jklymak requested a review from ianhi May 20, 2021 23:28
@ericpre
Copy link
Member Author

ericpre commented Jun 19, 2021

@QuLogic, thanks for the review, I have addressed all points!

@ericpre
Copy link
Member Author

ericpre commented Jun 28, 2021

@anntzer, @ianhi, @tacaswell, @QuLogic, is there anything left to do on this PR?

@anntzer
Copy link
Contributor

anntzer commented Jun 30, 2021

(Not that it adds much to the discussion as @tacaswell mostly summarized my points above, but I think that I finally realized why I am so attached to the old UI model: it mimicks the UI of text selection, where you can restart another selection by just clicking anywhere and selecting from there.)

@ericpre
Copy link
Member Author

ericpre commented Jun 30, 2021

(Not that it adds much to the discussion as @tacaswell mostly summarized my points above, but I think that I finally realized why I am so attached to the old UI model: it mimicks the UI of text selection, where you can restart another selection by just clicking anywhere and selecting from there.)

I see what you mean, however I would imagine that with the recent addition of drag_from_anywhere, changing the selection area is much easier and that it covers this case to a certain extent.

@tacaswell
Copy link
Member

@anntzer I think the current state captures the best of the old behavior (click outside of the selection region and make a new span) and the new (you can drag either edge and if you click on the middle you drag the whole span). Both of the new interaction modes are things that I personally wished for in my past-life (to either scan a fixed-width window across some line or to tweak it to be just the right width).

@QuLogic QuLogic merged commit 4013172 into matplotlib:master Jun 30, 2021
Comment on lines +1944 to +1946
interactive : bool, default: False
Whether to draw a set of handles that allow interaction with the
widget after it is drawn.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me the primary difference is whether the selector is still visible after the first selection.

When interactive=True I get a selector that persists, but I can still modify later. Coming from that context I would expect interactive=False to still show my selected region, but I cannot modify it anymore. This indicates that interactive is a misleading name.

When starting from scratch, I'd call this persistent, but given that we have span_stays keeping that is ok as well.


button : `.MouseButton` or list of `.MouseButton`
The mouse buttons which activate the span selector.

line_props : dict, default: None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there's no canonical line in a span. the name does not make it clear what this controls. I'd call these handle_props or handle_line_props if you want to be very explicit.


button : `.MouseButton` or list of `.MouseButton`
The mouse buttons which activate the span selector.

line_props : dict, default: None
Line properties with which the interactive line are drawn. Only used
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Line properties with which the interactive line are drawn. Only used
Properties of the handler lines at the edges of the span. Only used

@timhoffm
Copy link
Member

timhoffm commented Jun 30, 2021

🙄 8 minutes too late. Will open a follow-up PR.

@ericpre
Copy link
Member Author

ericpre commented Jul 1, 2021

Thanks everyone for the reviews, it has been very useful!

@timhoffm
Copy link
Member

timhoffm commented Jul 1, 2021

Thanks @ericpre for keeping up!

@larsoner
Copy link
Contributor

larsoner commented Jul 9, 2021

In MNE we allow users to update the selector colors, and have:

        selector.rect.set_color(color)
        selector.rectprops.update(dict(facecolor=color))

This now emits a deprecation warning from this PR, but it doesn't indicate how code should be migrated. I looked at this and #20558 and hoped / thought maybe I could find some selector.set_* or selector.handle_props or something to modify but I don't see anything. How should we update our code? (And it might be worth improving the deprecation warning to give some hints to anyone else who hits this issue.) Maybe with something like this?

selector.artists[0].set_color(color)

the artists[0] is the selector.rect. But this just seems like a hack workaround, and if there are properties held internally it will not "stick" so I'm guessing it's not the right idea...

@jklymak
Copy link
Member

jklymak commented Jul 9, 2021

@larsoner suggest you open an issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants