Reputation: 770
I am using iText 7.2.1.
I have multiple long articles of various lengths. What I need to do is:
Pick one article in the candidate set and add it into my document. The newly added article will be right following the previous one. There may be automatic page changing.
Check if this newly added article meets some criterion. (For example: Check if its ending line is at the right position of a page)
If not, undo this adding, and try next article in the candidate set.
There seems no "undo"s for a Document
. So I'm wondering if I can duplicate my current document to test. Or is there any other way to test before adding?
Upvotes: 0
Views: 134
Reputation: 2458
In the question's comments section the idea of relayout
was suggested, however, it hasn't been demonstrated how it can be efficiently applied to your case. This is how I see your demands:
I want to explicitly mention the word "layout" rather than "add": in the solution proposed below I will try layouting candidates without actually adding them to the document. Once the candidate is layouted, you can check it against your criteria and if it meets them, then the candidate should be added.
Below is the main part of the code. As you can see, here I do the following: until the requested number of paragraphs is added, I generate paragraphs of random size and check with the help of isParagraphAccepted
whether they are accepted or not. If true, then I add them to the document and reduce the number of paragraphs to be added.
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName));
Document doc = new Document(pdfDoc);
RootRenderer rootRenderer = doc.getRenderer();
Rectangle defaultArea = pdfDoc.getDefaultPageSize();
int paragraphsToAddCount = 10;
LoremIpsum lorem = LoremIpsum.getInstance();
int minLoremCount = 25;
int maxLoremCount = 50;
int counter = 0;
while (paragraphsToAddCount > 0) {
Paragraph p = new Paragraph(lorem.getParagraphs(minLoremCount, maxLoremCount));
if (isParagraphAccepted(p, rootRenderer, defaultArea)) {
doc.add(p);
paragraphsToAddCount--;
}
counter++;
}
System.out.println("We have considered " + counter + " paragraphs.");
doc.close();
The magic, however, is done in isParagraphAccepted
, so let's take a look:
boolean isParagraphAccepted(Paragraph p, RootRenderer rootRenderer, Rectangle defaultArea) {
Rectangle currentArea = null == rootRenderer.getCurrentArea()
? defaultArea
: rootRenderer.getCurrentArea().getBBox();
IRenderer paragraphRenderer = p.createRendererSubTree().setParent(rootRenderer);
LayoutResult layoutResult = paragraphRenderer.layout(new LayoutContext(new LayoutArea(0, currentArea)));
while (LayoutResult.FULL != layoutResult.getStatus()) {
currentArea = defaultArea;
paragraphRenderer = layoutResult.getOverflowRenderer();
layoutResult = paragraphRenderer.layout(new LayoutContext(new LayoutArea(0, currentArea)));
}
// checking against some criteria
return layoutResult.getOccupiedArea().getBBox().getHeight() > 500;
}
Basically, in this method the following is done: the pararaph gets layouted page after page until it's finally fully layouted and then I check the area it occupies on the last page against some criteria.
Upvotes: 3