Hey Eric, I'm CC-ing the devel list because some of this has
potentially far reaching consequences.
> In connection with the colorbar sizing problem I have been
> thinking about adding a function list to axes, with the
> functions to be executed early in the draw() method, to
> handle this sort of thing. Using this mechanism to handle
I think this is a very nice idea -- I saw a talk at pycon one year about
the utility of adding hooks, eg before_somefunc_hook and after_somefunc_hook
that are customizable *for every function in your API*. The questions are
1) what is the right data structure -- a single callable, a
sequence, or a dictionary registry with connect/disconnect
semantics (eg the backend event callback handler)
2) what is the signature (see below)
3) which artists should support it
Most elegant, but most expensive, is something like a ordered
dictionary which is supported for every artist. By renaming all the
artist draw methods _draw, we can do this quite simply in
backend_bases.Renderer with
def draw(self, renderer):
for func in self.before_draw_hook.ordered_values():
func(self, renderer)
self._draw(renderer)
for func in self.after_draw_hook.ordered_values():
func(self, renderer)
I think this could be really useful and would help handle problems
that crop up all the time -- how to handle physical layout problems
where we need the renderer to get size information like you are
experiencing with colorbar. This problem also crops up in a lot of
text layout problems. Unfortunately, draw time layout creates other
problems (sometimes users want this info at the API level), and order
effects becomes very important and potentially complicated. But that
said, given the current architecture, something like this would be a
definite improvement.
I'm inclined to use an ordered dictionary because one wants the
connect/disconnect semantics that keys make easy, and because ordering
matters. There is a python cookbook recipe for an ordered dictionary,
and we could easily roll our own. Because the calls are potentially
expensive, we might want an optimization like
class MyOrderedDictionary:
def __init__(blah):
self.isempty = True
so we can do
def draw(renderer):
if not self.before_draw_hook.isempty:
for func in self.before_draw_hook.ordered_values():
func(self, renderer)
self._draw(renderer)
if not self.after_draw_hook.isempty:
for func in self.after_draw_hook.ordered_values():
func(self, renderer)
Since 99% of the time I guess these will be empty and then we are just
adding a few attribute lookups and a boolean check for each draw.
JDH