Dynamic Height for Bounding Boxes

1,104 views
Skip to first unread message

Sam

unread,
Jan 28, 2009, 1:34:20 PM1/28/09
to Prawn
Greetings everyone,

I'm having trouble building a simple document that has several
sections spanning the entire width of the document, but which should
have dynamically expanding heights depending on what's contained
within them.

Currently I have several consecutive bounding_box's, and if I simply
do not specify a :height for the bounding_box call the content
displays fine, but the next bounding_box's content overlap the first
bounding_box, rather than starting after it. I've tried using
pdf.cursor and pdf.y for the coordinates of the second bounding_box
call, but with the same results.

Any guidance would be much appreciated.

Sam

Gregory Brown

unread,
Jan 28, 2009, 1:38:58 PM1/28/09
to prawn...@googlegroups.com
On Wed, Jan 28, 2009 at 1:34 PM, Sam <sam.p...@gmail.com> wrote:

> Currently I have several consecutive bounding_box's, and if I simply
> do not specify a :height for the bounding_box call the content
> displays fine, but the next bounding_box's content overlap the first
> bounding_box, rather than starting after it. I've tried using
> pdf.cursor and pdf.y for the coordinates of the second bounding_box
> call, but with the same results.
>
> Any guidance would be much appreciated.

I'd be happy to help you take a look at this problem, but to do that,
it'd be much better to work against some code samples rather than try
to describe the problem / solution in words. Can you code me up an
example of your problem?

-greg

--
Technical Blaag at: http://blog.majesticseacreature.com
Non-tech stuff at: http://metametta.blogspot.com
"Ruby Best Practices" Book now in O'Reilly Roughcuts:
http://rubybestpractices.com

Sam

unread,
Jan 28, 2009, 3:22:18 PM1/28/09
to Prawn
Hey Greg, thanks for the quick reply! I should have just posted a
sample in my original -- sorry bout that.

So in the following example of what I'm trying to do, I've got three
bounding_boxes (two of them with nested bounding_boxes) with the
margin bounding_box as an immediate parent. I simply want these three
bounding_boxes to display one after the other vertically down the
page. As it stands however, they stack all up on top of each other
smooshed at the top of the page. I realize that I can push the two
bottom bounding_boxes further down the page by specifying [0,
pdf.bounds.height - n], but I'm not always sure how large the content
of the bounding boxes will be, and would like them to collapse to fit.

Thanks again Greg,
Sam

pdf.bounding_box [0, pdf.bounds.height], :width => pdf.bounds.width
do
pdf.image "#{RAILS_ROOT}/public/images/favalogoheader.png"

pdf.bounding_box [100, pdf.bounds.height], :width => 200 do
pdf.font_size = 12
pdf.text "FAVA: Film and Video Arts Society"
pdf.font_size = 8
pdf.text 'some stuff here'
pdf.text 'some stuff here'
pdf.text 'some stuff here'
pdf.text 'some stuff here'
pdf.text 'some stuff here'
pdf.text 'some stuff here'
end

pdf.bounding_box [pdf.bounds.width - 150, pdf.bounds.height], :width
=> 150 do
pdf.font_size = 10
pdf.text "Invoice ##{@invoice.reference}", :align => :right
pdf.text "#{@invoice.invoice_date.strftime('%a %b %d
%Y')}", :align => :right
end
end

pdf.bounding_box [0, pdf.cursor], :width => pdf.bounds.width, :height
=> 60 do
pdf.line_width = 1
pdf.line pdf.bounds.top_left, pdf.bounds.top_right
pdf.stroke

pdf.bounding_box [0, pdf.bounds.height - 10], :width => 300 do
pdf.font_size = 10
if @invoice.is_for_user_entity?
pdf.text "#{@invoice.account.user_entity.full_name}", :size =>
12
pdf.text "#{@invoice.account.user_entity.address1}" if !
@invoice.account.user_entity.address1.blank?
pdf.text "#{@invoice.account.user_entity.address2}" if !
@invoice.account.user_entity.address2.blank?
pdf.text "#{@invoice.account.user_entity.city} #
{@invoice.account.user_entity.province} #
{@invoice.account.user_entity.postal_code}"
pdf.text "#
{@invoice.account.user_entity.primary_operator_first_name} #
{@invoice.account.user_entity.primary_operator_last_name} / #
{@invoice.accountuser_entity.primary_operator_contact_info}" if
primary_operator?(@invoice.account.user_entity)
elsif @invoice.is_floating_invoice?
pdf.text "#{@invoice.floating_first_name}"
pdf.text "#{@invoice.floating_last_name}"
pdf.text "#{@invoice.floating_contact_info}"
end

end

pdf.bounding_box [310, pdf.bounds.height - 10], :width => 300 do
# Some stuff will go here
end
end


pdf.bounding_box [0, pdf.cursor ], :width => pdf.bounds.width do
if !@invoice.notes.blank?
pdf.text "Invoice Notes: #{@invoice.notes}"
end
end


On Jan 28, 11:38 am, Gregory Brown <gregory.t.br...@gmail.com> wrote:

Sam

unread,
Jan 28, 2009, 3:25:09 PM1/28/09
to Prawn
Oh wow, that code paste was ugly -- here's a pastie: http://www.pastie.org/373510

-Sam
>     pdf.text "Invoice #...@invoice.reference}", :align => :right
>     pdf.text "#...@invoice.invoice_date.strftime('%a %b %d
> %Y')}", :align => :right
>   end
> end
>
> pdf.bounding_box [0, pdf.cursor], :width => pdf.bounds.width, :height
> => 60 do
>   pdf.line_width = 1
>   pdf.line pdf.bounds.top_left, pdf.bounds.top_right
>   pdf.stroke
>
>   pdf.bounding_box [0, pdf.bounds.height - 10], :width => 300 do
>     pdf.font_size = 10
>     if @invoice.is_for_user_entity?
>       pdf.text "#...@invoice.account.user_entity.full_name}", :size =>
> 12
>       pdf.text "#...@invoice.account.user_entity.address1}" if !
> @invoice.account.user_entity.address1.blank?
>       pdf.text "#...@invoice.account.user_entity.address2}" if !
> @invoice.account.user_entity.address2.blank?
>       pdf.text "#...@invoice.account.user_entity.city} #
> {...@invoice.account.user_entity.province} #
> {...@invoice.account.user_entity.postal_code}"
>       pdf.text "#
> {...@invoice.account.user_entity.primary_operator_first_name} #
> {...@invoice.account.user_entity.primary_operator_last_name} / #
> {...@invoice.accountuser_entity.primary_operator_contact_info}" if
> primary_operator?(@invoice.account.user_entity)
>     elsif @invoice.is_floating_invoice?
>       pdf.text "#...@invoice.floating_first_name}"
>       pdf.text "#...@invoice.floating_last_name}"
>       pdf.text "#...@invoice.floating_contact_info}"
>     end
>
>   end
>
>   pdf.bounding_box [310, pdf.bounds.height - 10], :width => 300 do
>     # Some stuff will go here
>   end
> end
>
> pdf.bounding_box [0, pdf.cursor ], :width => pdf.bounds.width do
>   if !...@invoice.notes.blank?
>     pdf.text "Invoice Notes: #...@invoice.notes}"

Jamis Buck

unread,
Jan 28, 2009, 3:28:17 PM1/28/09
to prawn...@googlegroups.com
If I had to hazard a guess, I'd guess it's because of using
pdf.bounds.height as the y argument, when the outer box has no height,
thus causing all boxes to be positioned at the same y coordinate.

- Jamis

Gregory Brown

unread,
Jan 28, 2009, 3:36:01 PM1/28/09
to prawn...@googlegroups.com
On Wed, Jan 28, 2009 at 3:28 PM, Jamis Buck <ja...@37signals.com> wrote:
>
> If I had to hazard a guess, I'd guess it's because of using
> pdf.bounds.height as the y argument, when the outer box has no height,
> thus causing all boxes to be positioned at the same y coordinate.

That's right. It seems like this example reflects the desired behavior.

==================

Prawn::Document.generate("foo.pdf") do

bounding_box bounds.top_left, :width => 400 do
bounding_box [0, cursor], :width => 200 do
text "La la la " * 50
end

bounding_box [50, cursor], :width => 250 do
text "La la la " * 50
end

bounding_box [100, cursor], :width => 100 do
text "la la la " * 50
end

text "la la la" * 50
end

end

`open foo.pdf`

==================

Does that clear anything up, Sam?

Sam

unread,
Jan 28, 2009, 4:00:23 PM1/28/09
to Prawn
Geniuses! You're both well deserving of all the praise I've seen
lavished upon you. Thanks for the unbelievably quick support, not to
mention both of your invaluable contributions to the community at
large. Fine examples you set for peons like myself to strive towards.

Much gratitude,
Sam

Sam

unread,
Jan 28, 2009, 5:14:03 PM1/28/09
to Prawn
Hey guys, I'm still having trouble with nested boxes. The trouble
seems to be because the pdf.cursor coordinate in Outer Box 2 has a
value that's snugging it up against the bottom edge of Inner Box 2,
rather than up against the bottom edge of Outer Box 1.

I've got another pastie of some example code with all the instance
variable references removed: http://www.pastie.org/373665

Any ideas?

Thanks again,
Sam

Gregory Brown

unread,
Jan 28, 2009, 5:23:59 PM1/28/09
to prawn...@googlegroups.com
On Wed, Jan 28, 2009 at 5:14 PM, Sam <sam.p...@gmail.com> wrote:
>
> Hey guys, I'm still having trouble with nested boxes. The trouble
> seems to be because the pdf.cursor coordinate in Outer Box 2 has a
> value that's snugging it up against the bottom edge of Inner Box 2,
> rather than up against the bottom edge of Outer Box 1.

Wait a second. You never set the height of Outer Box 1.
So since Inner Box 2 is the bottom box in there, wouldn't you expect
the bottom of Outer Box 1 to equal the bottom of Inner Box 2?

Or are you expecting the cursor to be at the bottom of Inner Box1
because that takes you deeper into the box? That's not how
bounding_box works without a height.
A cheap trick would be to swap your boxes so the longest one is the
last to be rendered.

That having been said, It looks like your master box, and all of your
outer bounding boxes are not needed.
Maybe try this without nesting first, because all three of those are
equivalent to the margin box.

-greg

Sam

unread,
Jan 28, 2009, 6:15:41 PM1/28/09
to Prawn
I suppose I expect Outer Box 1 to stretch in order to accommodate
whichever is the longer of Inner Box 1 and Inner Box 2, and for cursor
to then point to the bottom edge of the whole mess. In the case of the
example it would be Inner Box 1, but in my real life implementation it
could be either of them depending on some conditionals that have been
removed for simplicity's sake.

Inner Box 1 and Inner Box 2 sit side-by-side on the page, and I need
Outer Box 2 to span accross the entire page directly below that (or a
few points below it via a move_down). I guess the layout portion of my
brain is stuck in CSS land, which doesn't apply at all here I realize
- but is there a way to accomplish this kind of layout in order to
accommodate side-by-side bounding box's with dynamic content heights?
Even without the Master and Outer boxes, Inner Boxes 3 & 4 end up
overlapping whichever is the longer of Inner Boxes 1 & 2, in order to
butt up against the bottom edge of the shorter of the two.

Ideas? Thanks for hanging in there with me...
Sam


On Jan 28, 3:23 pm, Gregory Brown <gregory.t.br...@gmail.com> wrote:

Sam

unread,
Jan 28, 2009, 6:16:08 PM1/28/09
to Prawn
I suppose I expect Outer Box 1 to stretch in order to accommodate
whichever is the longer of Inner Box 1 and Inner Box 2, and for cursor
to then point to the bottom edge of the whole mess. In the case of the
example it would be Inner Box 1, but in my real life implementation it
could be either of them depending on some conditionals that have been
removed for simplicity's sake.

Inner Box 1 and Inner Box 2 sit side-by-side on the page, and I need
Outer Box 2 to span accross the entire page directly below that (or a
few points below it via a move_down). I guess the layout portion of my
brain is stuck in CSS land, which doesn't apply at all here I realize
- but is there a way to accomplish this kind of layout in order to
accommodate side-by-side bounding box's with dynamic content heights?
Even without the Master and Outer boxes, Inner Boxes 3 & 4 end up
overlapping whichever is the longer of Inner Boxes 1 & 2, in order to
butt up against the bottom edge of the shorter of the two.

Ideas? Thanks for hanging in there with me...
Sam


On Jan 28, 3:23 pm, Gregory Brown <gregory.t.br...@gmail.com> wrote:

Gregory Brown

unread,
Jan 28, 2009, 6:22:29 PM1/28/09
to prawn...@googlegroups.com
On Wed, Jan 28, 2009 at 6:15 PM, Sam <sam.p...@gmail.com> wrote:
>
> I suppose I expect Outer Box 1 to stretch in order to accommodate
> whichever is the longer of Inner Box 1 and Inner Box 2, and for cursor
> to then point to the bottom edge of the whole mess. In the case of the
> example it would be Inner Box 1, but in my real life implementation it
> could be either of them depending on some conditionals that have been
> removed for simplicity's sake.

I think the biggest problem is that this is not how bounding_box works
currently. But I don't see anything wrong with changing it.
This would fix your problem, I imagine.

Please file a ticket for this in Lighthouse to remind me.

Reply all
Reply to author
Forward
0 new messages