Skip to content
This repository

For a text artist, if it has a _bbox_patch associated with it, the contains test should reflect this. #1088

Merged
merged 3 commits into from over 1 year ago

4 participants

dhyams Michael Droettboom Benjamin Root Phil Elson
dhyams

For a text artist, if it has a _bbox_patch associated with it, the contains test should reflect this.

dhyams

This pull request is identical to #1072 but based on master.

Michael Droettboom
Owner

Seems fine to me.

lib/matplotlib/text.py
@@ -206,12 +206,18 @@ def contains(self,mouseevent):
206 206
         if not self.get_visible() or self._renderer is None:
207 207
             return False,{}
208 208
 
  209
+        if self._bbox_patch:
  210
+            patch_inside, patch_cattr =  self._bbox_patch.contains(mouseevent)
4
Phil Elson Collaborator
pelson added a note August 15, 2012

One idiom which I think helps clarity in the case where you are forced to handle data that you don't ever use is to call your variable _. In this case:

patch_inside, _ =  self._bbox_patch.contains(mouseevent)
dhyams
dhyams added a note August 15, 2012

Nice tip! I like it....but, in this case, I would rather see the unused variable stay as is, as a reminder to future readers that "maybe" it should be used. The "_" implies that it "definitely" shouldn't be used.

Benjamin Root Collaborator

Of course, a comment would also work fine to explain that...

Phil Elson Collaborator
pelson added a note August 15, 2012

But my stupid IDE can't read comments :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/matplotlib/text.py
((10 lines not shown))
209 215
         l,b,w,h = self.get_window_extent().bounds
210 216
         r, t = l+w, b+h
211 217
         
212 218
         x, y = mouseevent.x, mouseevent.y
213 219
         inside = (l <= x <= r and b <= y <= t)
214  
-        return inside, {}
  220
+        return (inside or patch_inside), {}
6
Benjamin Root Collaborator

Same question as before, shouldn't this return statement use patch_cattr instead of the empty dictionary? Otherwise, what is the point of saving patch_cattr?

dhyams
dhyams added a note August 15, 2012

I'll yield to whatever you guys want me to do there...as I had mentioned before, I am not sure exactly what role the second return value from contains() plays. I looked at all of the patches, and it looks to me like they all return an empty dict for that second arg anyway.

If you want me to return dict({}.items() + patch_cattr.items()) I can add that. I wasn't sure what the worse thing was to do...just return an empty dict straightaway (possibly has a problem in the future if patches start to return useful data there), or do the dict update (possibly has a problem in the future if the same key shows up in the two dictionaries).

Benjamin Root Collaborator

I prefer to have all my piping set correctly now rather than calling a plumber to find and fix the problem later. Unless there is a specific reason why we don't ever want the patch_cattr information (and that may very well be the case), I would pass it along so that it is available to the end user if they want it.

dhyams
dhyams added a note August 15, 2012

OK, will do. Just a nitpick though...this is not a "pass it along" situation, it's a "merge with existing results" situation...which could open the door to different, and harder to find, problems down the road.

Benjamin Root Collaborator

Merge with what other existing results? We have an empty dictionary and patch_cattr. If patch_inside is false, then patch_cattr is also empty. It is only if patch_inside is True that any possibility of a non-empty dictionary comes back, in which case, I may want that information. A particular usecase I can think of is selecting the contour labels interactively.

dhyams
dhyams added a note August 15, 2012

That's the way it is right now, but I thought we were talking about future proofing? In the future, someone might add attrs to return for the text part of the text object, and at that point, if you don't merge the two dicts, it gets lost.

The text object is made up (possibly) of two parts...the text and the bbox_patch. The contains test should return the union of those two results. Union of booleans, then union of the attrs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Refinement to the contains test; returns the _bbox_patch's containment
attributes if they are present.  It does this by merging those results with
the (presently empty) attributes for the text object.

Code also restructured slightly so that it will be more efficient.
41a3d80
dhyams

Is this one better?

Benjamin Root
Collaborator

@dhyams, you raise a good point that I didn't quite grok at first. We have a situation where we are treating the combination of two artist objects as one, and both of them has the potential of having user-supplied pick functions that can return their own dictionaries. These dictionaries may have common keys, in which case, naively merging them would produce an intelligible mess.

Just as a reference, I am referring to this feature of mpl: http://matplotlib.sourceforge.net/users/event_handling.html#object-picking

The problem here is that pretty much all of mpl never defines this dictionary, and the feature is designed totally for the end-user to take advantage of. However, I don't think the interface was completely thought through. I think the solution in this case is that it is the responsibility of the combined text/patch object to return a single dictionary. In other words, this is the proper place to address this issue.

Lacking any sort of precedence that I can see, I would suggest that the patch's dictionary is added as an entry to the text's dictionary, probably keyed as "patch". Assuming that the text object itself never has an entry called "patch", this should prevent any key collisions, and still provide useful information downstream to the caller. Thoughts?

dhyams

This sounds fine to me....maybe call the new key "_bbox_patch" or "bbox_patch"? Just trying to decrease the possibility of key collision.

Benjamin Root
Collaborator

Yes, I like that better.

Instead of trying to merge the containment attribute dicts from both …
…the text

and the bounding box, the bounding box's attributes are now a key within the
returned attribute dict.  The key is "bbox_patch".
834f4cb
dhyams

This one OK to merge now?

Benjamin Root
Collaborator

Yes, I guess so.

Benjamin Root WeatherGod merged commit 963506f into from August 20, 2012
Benjamin Root WeatherGod closed this August 20, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 3 unique commits by 1 author.

Aug 15, 2012
For a text artist, if it has a _bbox_patch associated with it, the co…
…ntains test should reflect this.
be50789
Refinement to the contains test; returns the _bbox_patch's containment
attributes if they are present.  It does this by merging those results with
the (presently empty) attributes for the text object.

Code also restructured slightly so that it will be more efficient.
41a3d80
Aug 16, 2012
Instead of trying to merge the containment attribute dicts from both …
…the text

and the bounding box, the bounding box's attributes are now a key within the
returned attribute dict.  The key is "bbox_patch".
834f4cb
This page is out of date. Refresh to see the latest.

Showing 1 changed file with 10 additions and 1 deletion. Show diff stats Hide diff stats

  1. 11  lib/matplotlib/text.py
11  lib/matplotlib/text.py
@@ -211,7 +211,16 @@ def contains(self,mouseevent):
211 211
         
212 212
         x, y = mouseevent.x, mouseevent.y
213 213
         inside = (l <= x <= r and b <= y <= t)
214  
-        return inside, {}
  214
+        cattr = {}
  215
+
  216
+        # if the text has a surrounding patch, also check containment for it,
  217
+        # and merge the results with the results for the text.
  218
+        if self._bbox_patch:
  219
+            patch_inside, patch_cattr =  self._bbox_patch.contains(mouseevent)
  220
+            inside = inside or patch_inside
  221
+            cattr["bbox_patch"] = patch_cattr
  222
+
  223
+        return inside, cattr 
215 224
 
216 225
     def _get_xy_display(self):
217 226
         'get the (possibly unit converted) transformed x, y in display coords'
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.