My last two commits had to do with generator flow issues. It all comes down to generators/base.py, and it’s giving me a headache… it still doesn’t work right.
The reports I’m generating have multiple levels of group header bands. Each active group header band should reprint on each new page; this didn’t work correctly sometimes, mainly if a group header pushed a detail band off the page. So I fixed that, no problem.
But then, I found that child bands would flow off the page if the parent band landed at the bottom (as utils.calculate_size() did not take child bands into account). I added that calculation to the height check I had already committed, and it worked. No problem.
Except… there’s still a problem. If you use auto_expand_height, the generator obligingly adjusts the space consumed by the band. But this addition space is consumed in the render_band function, after my extra size check. I can’t just move the size check down, as the band will have then been rendered; I need to advance the page (and reprint those darn group headers) before that happens.
Gah. So I’m stuck, for now. One of the reports I’m generating has a subreport that expands the detail band, and this sometimes screws up the page position (and those headers). I can’t see any way to avoid having the subreport, and the whole reason I used a child band was to ensure that a specific block of information floats at the bottom below that subreport.
I’m coming to the conclusion that Geraldo is structurally flawed. Here’s how I see the flow working correctly:
- Each row of the data source generates an in-memory band structure of some sort. A simple list would actually work, where every item in the list would have a relative vertical position and height associated with it. The whole band, including subreports and child bands, would be generated into this structure, and the height could be calculated by a simple iterative bounding box algorithm. If you were really clever, the band structure could adjust the height automatically each time an element was generated into it.
- But, the band structure I’ve just described hasn’t been rendered yet, just queued. The generator loop would check to see if there is enough room left on the page for this band; if there is not, it would trigger a new page, re-render the current group header bands, and only then render the detail band.
The problem I see with Geraldo is, obviously, this isn’t being done.
But Geraldo represents a lot of otherwise-good work. I don’t want to just throw it away. Can it be fixed? Possibly…
What needs doing is that whole render-the-detail-first thing. If, instead of rendering directly into the Reportlab canvas, the detail band could be rendered into a sort of side-canvas or pseudo-canvas first, the correct size could then be figured accurately. One of the main issues with this is the fact that the generator is looping; my fixes described above involve breaking out of the loop before the rendering takes place. I suspect I’ll have to render into my side-canvas, breaking if necessary, and thus causing the band to render twice (as the next pass through the loop would find the same record ready to process, just as it does now).
I don’t like that solution on the surface; it will be important to ensure that functions called from detail band rendering do not produce side effects, since they would effectively double up. (This “shouldn’t” happen, of course.) I’ll also have to verify that this procedure won’t throw off any running totals being maintained by Geraldo… and this is something that certainly will happen, so I can’t handwave it.
Egad. Time to call it a night, and hope I wake up smart enough to do this.