John,
I had some questions about this resize work. Here is the code for resize from backend_gtk.py:
def resize(self, w, h):
'set the drawing area size in pixels'
winw, winh = self.parent.parent.get_size()
tmp, tmp, myw, myh = self.allocation
padw = winw-myw
padh = winh-myh
self.parent.parent.resize(w+padw, h+padh)
I'm a little concerned about this implementation. It looks like the widget is telling it's parent's parent to resize. Doesn't this mean that the ability of the widget to be used as a modular component is reduced because this code requires a certain parent child relationship?
I think it's fairly important that a widget have only very minimum interactions with it's parent. Is there some way this could be implemented that doesn't require the child widget to be calling methods on the parent?
If I understand the basic premise you've outlined below, you want a resize in the child (the drawing widget) to cause the parent window to resize. Only the parent can figure out what it's size needs to be (since it knows about it's margins, toolbars, etc). On the surface, it seems like there are two ways to handling this:
1) Tell the window to resize the canvas. The window can use it's own layout classes, etc and correctly resize itself and the canvas.
2) Tell the canvas to resize and have this trigger a window resize.
I think the first option is much cleaner. However, if that isn't possible, I suggest that we do something like this:
- Tell the canvas to resize. It should resize itself and emit some type of 'plotCanvasResize' signal (GUI callback).
- When the window is originally constructed, it would attach a method on the window to this signal so that we basically get the same behavior as 1) above. Telling the canvas to resize emits the signal which calls the window method to do the real resizing. The canvas widget never knows that it's part of the window at all.
Of course this assumes that we have access to signal/slot (in Qt terms) systems in the Python layer. I'd also suggest that we stay away from calling it 'resize' since most GUI toolkits already have resize methods/attributes that mean very specific things.
Thoughts?
Ted
There is a new method in the figure canvas in CVS that I would like
the maintainers of the various GUI backends to implement
class FigureCanvasYourBackend
def resize(self, w, h):
"""
set the canvas size in pixels
"""
pass
This should set the canvas (not window) size and trigger a GUI resize
event so that the window is resized accordingly. There is a reference
implementation in backend_gtk.py. You should be able to lift the
logic for computing the new canvas size directly from that code.
Among other things, this will allow better control of the canvas size
from a script or shell. Eg, the following works with GTKAgg in an
interactive session:
In [1]: fig = figure()
In [2]: fig.set_figsize_inches(3,4,forward=True)
In [3]: fig.canvas.resize(500,600)
Ie, you can set the canvas size either in pixels or inches depending
on which method you choose.
Also, I added a new connect signal 'resize_event' that triggers a
backend_bases.ResizeEvent on a canvas.resize. You should call
self.resize_event()
from the part of your code that handles GUI configure events (see for
example the GTK and GTKAgg backends). Note depending on your toolkit,
you may not want to call this from the FigureCanvas.resize method.
Eg, in GTK* calling "canvas.resize" triggers a call to
canvas.configure_event, which in turn sets the new figure size
properties and once all this is done, calls canvas.resize_event.
Here is some test code
from pylab import figure, connect, show
fig = figure()
def resize(event):
print 'resize canvas', event.width, event.height
connect('resize_event', resize)
show()
Checking in lib/matplotlib/backend_bases.py;
/cvsroot/matplotlib/matplotlib/lib/matplotlib/backend_bases.py,v <-- backend_bases.py
new revision: 1.69; previous revision: 1.68
Thanks!
JDH
Ted Drain Jet Propulsion Laboratory ted.drain@...179...