I hadn't put much thought about passing rcParams as a parameter, as
load_plugins wasn't supposed to be called manually, but rather called
automatically when importing 'matplotlib.plugins'.
The code I had sent previously was more proof of concept of what could
be done with the plugin system. I like your ideas of how to add buttons
to the toolbar, so I implemented it last night. Now in the .matplotlibrc
file you can do:
toolbar.widget : print, print, prints figure, mprint, print_button
toolbar.connect : print.clicked -> nothing.do_toggle
toolbar.widget : nothing, nothing, does nothing, mprint, nothing_button
There are several things happening here:
(1) I had to alter __init__.py some, so that rcparams acted more like
opt.parse. The default behavior is the exact same as usual, except that
there is an addition. Normally for an entry you have:
There is now an extra optional field, which defaults to 'store', but can
also take on the value of 'append':
[None, validate_x, 'append']
Thus, several entries of 'toolbar.widget', will add append each entry to
a big list.
(2) The fields of 'toolbar.widget' are:
<name>, <text>, <tooltip>, <module>, <class>
The name is needed for the toolbar.connect, which I will get to shortly.
The text and tooltip, are the same as before. The module is required, as
although it is loaded as plugin, the toolbar code that creates widgets
from these, still needs to import something. The class is a child class
(3) The reason for creating a 'toolbar_widget' class, is to handle the
complexity of signalling between buttons that you mention. Basically it
is your generic signal/slot design, where one widget's signal can be
connected to another widget's slot. Thus the line:
toolbar.connect: print.clicked -> nothing.do_toggle
This uses the named widget (<name>) to connect it's signal (clicked) to
the other widget's slot (do_toggle).
While currently the code only supports buttons, I thought it might be
wise to allow other widget types. The backends can figure out what to
render on the class type.
(4) backend_bases.py: added a 'widgets' dict, that is loaded with
_init_toolbar from the rcParams files. The connections are then iterated
through, so the newly loaded widgets are all connected correctly.
(5) backend_gtk: changed to work with the new backend_bases.py widget ..
basically just iterates through 'self.widgets', and adds them to the toolbar
All the code (hopefully, let me know if it's not working/I left
something out) can be found:
I included a patch in the file for all the changes to the code, which
should hopefully work. As well, the new files created, and changed files
are also in the directory:
* mprint.py: gets placed in your plugin directory, and defines the
print_button, and nothing_button.
* plugins.py: the plugin code
* toolbar_widget.py: defines the toolbar_widget's, which are used in mprint
The code is still pretty rough, and small things like allowing for more
than one plugin directory hasn't yet been addressed (or going through
As far as changing the configuration midsession, the toolbar would have
to be reinitialized.
>I tried out your code and have a few questions.
>Your example only works on the current figure toolbar - it this
>desirable, or would it be better to modify the default toolbar? Also,
>how do you use it? After your figure is realized, do you call
> >>> load_plugins(rcParams)
>to get your buttons? That seems like it would be cumbersome to have
>to do this with every figure....
>And why does load_plugins take rcParams as an arg rather than work on
>the rcParams default? Do you plan on keeping different params with a
>different plugins directories?
>I may not be understanding how your code is supposed to work, but I
>was envisioning something a little different after reading your
>original post. I thought something along the lines of the following
># format is Name, Tooltip, image basename, callback
>plugins.dirs : /path/to/plugins1:/path/to/plugins2
>toolbar.button : Home, Reset original view, home_icon, mybackend.home
>toolbar.button : Back, Back to previous view, back_icon, mybackend.back
>toolbar.button : Forward, Forward to next view, forward_icon, mybackend.forward
>toolbar.button : Pan, Pan axes with left mouse, zoom with right, move_icon, mybackend.pan
>toolbar.button : Zoom, Zoom to rectangle, zoom_to_rect, mybackend.zoom
>toolbar.button : Print, Print to PS, print_icon, plugins.print_ps
>The order of the toolbar.button calls would determine which buttons
>were placed in the toolbar and in what order. mybackend would be a
>special string that matplotlib would use to substitute in for the
>current backend, and each backend would implement these functions.
>plugins (in the example plugins.print_ps) is a python code dir
>somewhere in the plugins.dirs search path. Thus the same code could
>be used to both build the default toolbar and used to customize it
>(remove buttons, change their order, add user buttons).
>I used icon names without extensions above because the different
>backends generally need icons of different types, and the backend
>could be responsible for supplying the extension. GTK could also
>detect special names like STOCK_PRINT and handle those.
>One thing this setup doesn't provide for is the ability to easily
>switch to different configurations in the middle of an interactive
>session. Is this important?
>Another design issue that comes to mind is how to handle communication
>between buttons. In the current toolbar2 design, when the zoom to
>rectangle button is pressed, the pan/zoom callbacks are disconnected
>and vis-a-versa. Presumably a more sophisticated model would have to
>be used to handle the connection and disconnection of multiple buttons
>that want to listen in on press/motion events.
>It would provide a nice framework for supporting user contributions,
>eg measurement tools, other navigation tools, etc...
>SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
>100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
>Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
>Matplotlib-devel mailing list