gettalong / hexapdf

Versatile PDF creation and manipulation for Ruby
https://hexapdf.gettalong.org
Other
1.21k stars 69 forks source link

How to create arbitratry groups of content (akin to CSS's div) at the Composer level? #267

Closed freesteph closed 7 months ago

freesteph commented 11 months ago

Hello, I'm trying to switch our document creation to HexaPDF but I'm struggling to understand how to create arbitrary bounding boxes to allow fitting an image and some text together for example.

Think about your typical header = image + some text, and wanting to move that header content as a unit.

I've looked into InlineBox but I can't figure out how to add one via the Composer interface. Canvas and pages feel too low-level for Composer too, so hopefully you can shed some light on this.

And thank you for your work!

gettalong commented 11 months ago

If you have a component, like an image and some text, you would usually create a subclass of HexaPDF::Layout::Box and define how those two would be laid out together (e.g. if there is enough width side-by-side, else try image above text).

I get that this might be too much for simple things like an image that should always be to the left of some text. For such use-cases I will most likely implement another generic container boxes RowBox that just puts the child boxes next to each other. There is also a request to implement something akin to the CSS flex box :grin:

As for inline boxes: You can create them with HexaPDF::Document::Layout#inline_box method which would wrap any other box as an inline box. And such an inline box can be used together with the #formatted_text_box method that is also available on the composer (see its documentation for a visual example of such an inline box).

gettalong commented 7 months ago

@freesteph The latest release of HexaPDF features a new ContainerBox class that is just a simple wrapper around child boxes, see https://hexapdf.gettalong.org/documentation/api/HexaPDF/Layout/ContainerBox.html

By appropriately setting the style properties align, valign and mask_mode which were also recent additions, you can achieve left-to-right, right-to-left, top-to-bottom and bottom-to-top layouts.

And it will allow you to move child boxes as a unit: image

In the above case there are three text boxes with "Some", "text" and "here" inside the container box, vertically aligned to the top, center and bottom of the container box.

I think this should make your use-case work.

freesteph commented 7 months ago

Thank you so much! Will give it a try soon.