10000 DOC : move MEP9 · matplotlib/matplotlib@7884afc · GitHub
[go: up one dir, main page]

Skip to content

Commit 7884afc

Browse files
committed
DOC : move MEP9
1 parent e07dc2d commit 7884afc

File tree

2 files changed

+216
-0
lines changed

2 files changed

+216
-0
lines changed

doc/devel/MEP/MEP09.rst

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
==================================
2+
MEP9: Global interaction manager
3+
==================================
4+
5+
Add a global manager for all user interactivity with artists; make any
6+
artist resizeable, moveable, highlightable, and selectable as desired
7+
by the user.
8+
9+
Status
10+
======
11+
**Discussion**
12+
13+
Branches and Pull requests
14+
==========================
15+
https://github.com/dhyams/matplotlib/tree/MEP9
16+
17+
Abstract
18+
========
19+
20+
The goal is to be able to interact with matplotlib artists in a very
21+
similar way as drawing programs do. When appropriate, the user should
22+
be able to move, resize, or select an artist that is already on the
23+
canvas. Of course, the script writer is ultimately in control of
24+
whether an artist is able to be interacted with, or whether it is
25+
static.
26+
27+
This code to do this has already been privately implemented and
28+
tested, and would need to be migrated from its current "mixin"
29+
implementation, to a bona-fide part of matplotlib.
30+
31+
The end result would be to have four new keywords available to
32+
matplotlib.artist.Artist: _moveable_, _resizeable_, _selectable_, and
33+
_highlightable_. Setting any one of these keywords to True would
34+
activate interactivity for that artist.
35+
36+
In effect, this MEP is a logical extension of event handling in
37+
matplotlib; matplotlib already supports "low level" interactions like
38+
left mouse presses, a key press, or similar. The MEP extends the
39+
support to the logical level, where callbacks are performed on the
40+
artists when certain interactive gestures from the user are detected.
41+
42+
Detailed description
43+
====================
44+
45+
This new functionality would be used to allow the end-user to better
46+
interact with the graph. Many times, a graph is almost what the user
47+
wants, but a small repositioning and/or resizing of components is
48+
necessary. Rather than force the user to go back to the script to
49+
trial-and-error the location, and simple drag and drop would be
50+
appropriate.
51+
52+
Also, this would better support applications that use matplotlib;
53+
here, the end-user has no reasonable access or desire to edit the
54+
underlying source in order to fine-tune a plot. Here, if matplotlib
55+
offered the capability, one could move or resize artists on the canvas
56+
to suit their needs. Also, the user should be able to highlight (with
57+
a mouse over) an artist, and select it with a double-click, if the
58+
application supports that sort of thing. In this MEP, we also want to
59+
support the highlighting and selection natively; it is up to
60+
application to handle what happens when the artist is selected. A
61+
typical handling would be to display a dialog to edit the properties
62+
of the artist.
63+
64+
In the future, as well (this is not part of this MEP), matplotlib
65+
could offer backend-specific property dialogs for each artist, which
66+
are raised on artist selection. This MEP would be a necessary
67+
stepping stone for that sort of capability.
68+
69+
There are currently a few interactive capabilities in matplotlib
70+
(e.g. legend.draggable()), but they tend to be scattered and are not
71+
available for all artists. This MEP seeks to unify the interactive
72+
interface and make it work for all artists.
73+
74+
The current MEP also includes grab handles for resizing artists, and
75+
appropriate boxes drawn when artists are moved or resized.
76+
77+
Implementation
78+
==============
79+
* Add appropriate methods to the "tree" of artists so that the
80+
interactivity manager has a consistent interface for the
81+
interactivity manager to deal with. The proposed methods to add to
82+
the artists, if they are to support interactivity, are:
83+
* get_pixel_position_ll(self): get the pixel position of the lower
84+
left corner of the artist's bounding box
85+
* get_pixel_size(self): get the size of the artist's bounding box,
86+
in pixels
87+
* set_pixel_position_and_size(self,x,y,dx,dy): set the new size of
88+
the artist, such that it fits within the specified bounding box.
89+
* add capability to the backends to 1) provide cursors, since these
90+
are needed for visual indication of moving/resizing, and 2) provide
91+
a function that gets the current mouse position
92+
* Implement the manager. This has already been done privately (by
93+
dhyams) as a mixin, and has been tested quite a bit. The goal would
94+
be to move the functionality of the manager into the artists so that
95+
it is in matplotlib properly, and not as a "monkey patch" as I
96+
currently have it coded.
97+
98+
99+
100+
Current summary of the mixin
101+
============================
102+
103+
(Note that this mixin is for now just private code, but can be added
104+
to a branch obviously)
105+
106+
InteractiveArtistMixin:
107+
108+
Mixin class to make any generic object that is drawn on a matplotlib
109+
canvas moveable and possibly resizeable. The Powerpoint model is
110+
followed as closely as possible; not because I'm enamoured with
111+
Powerpoint, but because that's what most people understand. An artist
112+
can also be selectable, which means that the artist will receive the
113+
on_activated() callback when double clicked. Finally, an artist can
114+
be highlightable, which means that a highlight is drawn on the artist
115+
whenever the mouse passes over. Typically, highlightable artists will
116+
also be selectable, but that is left up to the user. So, basically
117+
there are four attributes that can be set by the user on a per-artist
118+
basis:
119+
120+
* highlightable
121+
* selectable
122+
* moveable
123+
* resizeable
124+
125+
To be moveable (draggable) or resizeable, the object that is the
126+
target of the mixin must support the following protocols:
127+
128+
* get_pixel_position_ll(self)
129+
* get_pixel_size(self)
130+
* set_pixel_position_and_size(self,x,y,sx,sy)
131+
132+
Note that nonresizeable objects are free to ignore the sx and sy
133+
parameters. To be highlightable, the object that is the target of the
134+
mixin must also support the following protocol:
135+
136+
* get_highlight(self)
137+
138+
Which returns a list of artists that will be used to draw the highlight.
139+
140+
If the object that is the target of the mixin is not an matplotlib
141+
artist, the following protocols must also be implemented. Doing so is
142+
usually fairly trivial, as there has to be an artist *somewhere* that
143+
is being drawn. Typically your object would just route these calls to
144+
that artist.
145+
146+
* get_figure(self)
147+
* get_axes(self)
148+
* contains(self,event)
149+
* set_animated(self,flag)
150+
* draw(self,renderer)
151+
* get_visible(self)
152+
153+
The following notifications are called on the artist, and the artist
154+
can optionally implement these.
155+
156+
* on_select_begin(self)
157+
* on_select_end(self)
158+
* on_drag_begin(self)
159+
* on_drag_end(self)
160+
* on_activated(self)
161+
* on_highlight(self)
162+
* on_right_click(self,event)
163+
* on_left_click(self,event)
164+
* on_middle_click(self,event)
165+
* on_context_click(self,event)
166+
* on_key_up(self,event)
167+
* on_key_down(self,event)
168+
169+
The following notifications are called on the canvas, if no
170+
interactive artist handles the event:
171+
172+
* on_press(self,event)
173+
* on_left_click(self,event)
174+
* on_middle_click(self,event)
175+
* on_right_click(self,event)
176+
* on_context_click(self,event)
177+
* on_key_up(self,event)
178+
* on_key_down(self,event)
179+
180+
The following functions, if present, can be used to modify the
181+
behavior of the interactive object:
182+
183+
* press_filter(self,event) # determines if the object wants to have
184+
the press event routed to it
185+
* handle_unpicked_cursor() # can be used by the object to set a cursor
186+
as the cursor passes over the object when it is unpicked.
187+
188+
Supports multiple canvases, maintaining a drag lock, motion notifier,
189+
and a global "enabled" flag per canvas. Supports fixed aspect ratio
190+
resizings by holding the shift key during the resize.
191+
192+
Known problems:
193+
194+
* Zorder is not obeyed during the selection/drag operations. Because
195+
of the blit technique used, I do not believe this can be fixed. The
196+
only way I can think of is to search for all artists that have a
197+
zorder greater then me, set them all to animated, and then redraw
198+
them all on top during each drag refresh. This might be very slow;
199+
need to try.
200+
* the mixin only works for wx backends because of two things: 1) the
201+
cursors are hardcoded, and 2) there is a call to
202+
wx.GetMousePosition() Both of these shortcomings are reasonably
203+
fixed by having each backend supply these things.
204+
205+
Backward compatibility
206+
======================
207+
208+
No problems with backward compatibility, although once this is in
209+
place, it would be appropriate to obsolete some of the existing
210+
interactive functions (like legend.draggable())
211+
212+
Alternatives
213+
============
214+
215+
None that I know of.

doc/devel/MEP/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Matplotlib Enhancement Proposals
1414

1515
template
1616
MEP08
17+
MEP09
1718
MEP10
1819
MEP11
1920
MEP12

0 commit comments

Comments
 (0)
0