Skip to content

Commit 01634ed

Browse files
committed
Improve LayoutResult.NOTHING processing of the cells and a container itself, add proper forced placement logic
DEVSIX-8329
1 parent 098c8d1 commit 01634ed

16 files changed

+86
-55
lines changed

layout/src/main/java/com/itextpdf/layout/renderer/GridContainerRenderer.java

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ This file is part of the iText (R) project.
3131
import com.itextpdf.layout.properties.ContinuousContainer;
3232
import com.itextpdf.layout.properties.GridFlow;
3333
import com.itextpdf.layout.properties.GridValue;
34+
import com.itextpdf.layout.properties.OverflowPropertyValue;
3435
import com.itextpdf.layout.properties.Property;
3536
import com.itextpdf.layout.properties.UnitValue;
3637

@@ -85,31 +86,15 @@ public LayoutResult layout(LayoutContext layoutContext) {
8586
Grid grid = constructGrid(this, actualBBox);
8687
GridLayoutResult layoutResult = layoutGrid(layoutContext, actualBBox, grid);
8788

88-
//TODO DEVSIX-8329 improve nothing processing, consider checking for cause of nothing here?
89-
//TODO DEVSIX-8329 improve forced placement logic
90-
if (layoutResult.getOverflowRenderers().isEmpty() && layoutResult.getSplitRenderers().isEmpty()) {
89+
if (layoutResult.getOverflowRenderers().isEmpty()) {
9190
this.occupiedArea = calculateContainerOccupiedArea(layoutContext, grid, true);
9291
return new LayoutResult(LayoutResult.FULL, this.occupiedArea, null, null);
9392
} else if (layoutResult.getSplitRenderers().isEmpty()) {
94-
if (Boolean.TRUE.equals(this.<Boolean>getProperty(Property.FORCED_PLACEMENT))) {
95-
this.occupiedArea = calculateContainerOccupiedArea(layoutContext, grid, true);
96-
return new LayoutResult(LayoutResult.FULL, this.occupiedArea, this, null);
97-
}
9893
IRenderer cause = this;
9994
if (!layoutResult.getCauseOfNothing().isEmpty()) {
10095
cause = layoutResult.getCauseOfNothing().get(0);
10196
}
10297
return new LayoutResult(LayoutResult.NOTHING, null, null, this, cause);
103-
} else if (layoutResult.getOverflowRenderers().isEmpty()) {
104-
final ContinuousContainer continuousContainer = this.<ContinuousContainer>getProperty(
105-
Property.TREAT_AS_CONTINUOUS_CONTAINER_RESULT);
106-
if (continuousContainer != null) {
107-
continuousContainer.reApplyProperties(this);
108-
}
109-
this.childRenderers.clear();
110-
this.addAllChildRenderers(layoutResult.getSplitRenderers());
111-
this.occupiedArea = calculateContainerOccupiedArea(layoutContext, grid, true);
112-
return new LayoutResult(LayoutResult.FULL, this.occupiedArea, this, null);
11398
} else {
11499
this.occupiedArea = calculateContainerOccupiedArea(layoutContext, grid, false);
115100
return new LayoutResult(LayoutResult.PARTIAL, this.occupiedArea,
@@ -118,6 +103,16 @@ public LayoutResult layout(LayoutContext layoutContext) {
118103
}
119104
}
120105

106+
/**
107+
* {@inheritDoc}
108+
*/
109+
@Override
110+
public void addChild(IRenderer renderer) {
111+
renderer.setProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE);
112+
renderer.setProperty(Property.OVERFLOW_Y, OverflowPropertyValue.VISIBLE);
113+
super.addChild(renderer);
114+
}
115+
121116
private AbstractRenderer createSplitRenderer(List<IRenderer> children) {
122117
AbstractRenderer splitRenderer = (AbstractRenderer) getNextRenderer();
123118
splitRenderer.parent = parent;
@@ -131,6 +126,7 @@ private AbstractRenderer createSplitRenderer(List<IRenderer> children) {
131126
}
132127

133128
private AbstractRenderer createOverflowRenderer(List<IRenderer> children) {
129+
// TODO DEVSIX-8340 - We put the original amount of rows into overflow container.
134130
GridContainerRenderer overflowRenderer = (GridContainerRenderer) getNextRenderer();
135131
overflowRenderer.isFirstLayout = false;
136132
overflowRenderer.parent = parent;
@@ -145,30 +141,39 @@ private AbstractRenderer createOverflowRenderer(List<IRenderer> children) {
145141
private GridLayoutResult layoutGrid(LayoutContext layoutContext, Rectangle actualBBox, Grid grid) {
146142
GridLayoutResult layoutResult = new GridLayoutResult();
147143
ensureTemplateValuesFit(grid, actualBBox);
148-
//TODO DEVSIX-8329 improve forced placement logic, right now if we have a cell which could not be fitted on its
149-
// area or returns nothing as layout result RootRenderer sets FORCED_PLACEMENT on this class instance.
150-
// And basically every cell inherits this value and force placed, but we only need to force place cells
151-
// which were not fitted originally.
144+
152145
for (GridCell cell : grid.getUniqueGridCells(Grid.GridOrder.ROW)) {
153-
//If cell couldn't fit during cell layout area calculation than we need to put such cell straight to
154-
//nothing result list
155-
if (!cell.isValueFitOnCellArea()) {
156-
layoutResult.getOverflowRenderers().add(cell.getValue());
157-
layoutResult.getCauseOfNothing().add(cell.getValue());
158-
continue;
159-
}
160-
//Calculate cell layout context by getting actual x and y on parent layout area for it
146+
// Calculate cell layout context by getting actual x and y on parent layout area for it
161147
LayoutContext cellContext = getCellLayoutContext(layoutContext, actualBBox, cell);
162-
//We need to check for forced placement here, because otherwise we would infinitely return partial result.
163-
if (!Boolean.TRUE.equals(this.<Boolean>getProperty(Property.FORCED_PLACEMENT))
164-
&& !actualBBox.contains(cellContext.getArea().getBBox())) {
165-
layoutResult.getOverflowRenderers().add(cell.getValue());
166-
continue;
167-
}
168148

169149
IRenderer cellToRender = cell.getValue();
170-
cellToRender.setProperty(Property.FILL_AVAILABLE_AREA, true);
171150
cellToRender.setProperty(Property.COLLAPSING_MARGINS, Boolean.FALSE);
151+
152+
// Now set the height for the individual items
153+
// We know cell height upfront and this way we tell the element what it can occupy
154+
Rectangle cellBBox = cellContext.getArea().getBBox();
155+
if (!cellToRender.hasProperty(Property.HEIGHT)) {
156+
final Rectangle rectangleWithoutBordersMarginsPaddings = cellBBox.clone();
157+
if (cellToRender instanceof AbstractRenderer) {
158+
final AbstractRenderer abstractCellRenderer = ((AbstractRenderer) cellToRender);
159+
// We subtract margins/borders/paddings because we should take into account that
160+
// borders/paddings/margins should also fit into a cell.
161+
if (AbstractRenderer.isBorderBoxSizing(cellToRender)) {
162+
abstractCellRenderer.applyMargins(rectangleWithoutBordersMarginsPaddings, false);
163+
} else {
164+
abstractCellRenderer.applyMarginsBordersPaddings(rectangleWithoutBordersMarginsPaddings, false);
165+
}
166+
}
167+
168+
cellToRender.setProperty(Property.HEIGHT,
169+
UnitValue.createPointValue(rectangleWithoutBordersMarginsPaddings.getHeight()));
170+
}
171+
172+
// Adjust cell BBox to the remaining part of the layout bbox
173+
// This way we can layout elements partially
174+
cellBBox.setHeight(cellBBox.getTop() - actualBBox.getBottom())
175+
.setY(actualBBox.getY());
176+
172177
LayoutResult cellResult = cellToRender.layout(cellContext);
173178

174179
if (cellResult.getStatus() == LayoutResult.NOTHING) {

layout/src/test/java/com/itextpdf/layout/element/GridContainerTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ public void threeColumnsWithSquareCellAndCellWithExplicitHeightTest() throws IOE
489489

490490
try (Document document = new Document(new PdfDocument(new PdfWriter(filename)))) {
491491
GridContainer grid = new GridContainer();
492+
grid.setBackgroundColor(ColorConstants.GREEN);
492493
SolidBorder border = new SolidBorder(ColorConstants.BLUE, 1);
493494
grid.setProperty(Property.GRID_TEMPLATE_COLUMNS, templateColumns);
494495
Paragraph paragraph1 = new Paragraph("One");

layout/src/test/java/com/itextpdf/layout/element/gridcontainer/GridContainerLayoutTest.java

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ This file is part of the iText (R) project.
3535
import com.itextpdf.layout.borders.SolidBorder;
3636
import com.itextpdf.layout.element.Div;
3737
import com.itextpdf.layout.element.GridContainer;
38+
import com.itextpdf.layout.element.Image;
3839
import com.itextpdf.layout.element.Paragraph;
3940
import com.itextpdf.layout.element.Text;
41+
import com.itextpdf.layout.logs.LayoutLogMessageConstant;
4042
import com.itextpdf.layout.properties.BackgroundImage;
4143
import com.itextpdf.layout.properties.BackgroundRepeat;
4244
import com.itextpdf.layout.properties.BackgroundRepeat.BackgroundRepeatValue;
@@ -45,6 +47,9 @@ This file is part of the iText (R) project.
4547
import com.itextpdf.layout.properties.Property;
4648
import com.itextpdf.layout.properties.UnitValue;
4749
import com.itextpdf.test.ExtendedITextTest;
50+
import com.itextpdf.test.LogLevelConstants;
51+
import com.itextpdf.test.annotations.LogMessage;
52+
import com.itextpdf.test.annotations.LogMessages;
4853
import com.itextpdf.test.annotations.type.IntegrationTest;
4954

5055
import java.io.IOException;
@@ -198,26 +203,48 @@ public void emptyGridContainerTest() throws IOException, InterruptedException {
198203
DESTINATION_FOLDER, "diff"));
199204
}
200205

206+
// TODO DEVSIX-8340
207+
@Test
208+
public void overflowGridContainerTest() throws IOException, InterruptedException {
209+
String fileName = DESTINATION_FOLDER + "overflowGridContainer.pdf";
210+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(fileName));
211+
Document document = new Document(pdfDocument);
201212

202-
private GridContainer createGridBoxWithSizedDiv() {
203-
GridContainer gridcontainer0 = new GridContainer();
213+
GridContainer gridcontainer0 = createGridBoxWithText();
204214

205-
gridcontainer0.setProperty(Property.COLUMN_GAP_BORDER, null);
206-
gridcontainer0.setProperty(Property.GRID_TEMPLATE_COLUMNS,
207-
Arrays.asList(new UnitValue(1, 150.0f), new UnitValue(1, 150.0f), new UnitValue(1, 150.0f)));
208-
gridcontainer0.setProperty(Property.COLUMN_GAP, 12.0f);
209-
gridcontainer0.setBackgroundColor(ColorConstants.RED);
210-
for (int i = 0; i < 4; i++) {
211-
Div div1 = new Div();
212-
div1.setBackgroundColor(ColorConstants.YELLOW);
213-
div1.setHeight(20);
214-
div1.setWidth(30);
215-
div1.setProperty(Property.COLUMN_GAP_BORDER, null);
216-
div1.setProperty(Property.COLUMN_GAP, 12.0f);
217-
gridcontainer0.add(div1);
218-
}
219-
return gridcontainer0;
215+
gridcontainer0.setBackgroundColor(ColorConstants.MAGENTA);
216+
gridcontainer0.setProperty(Property.GRID_TEMPLATE_ROWS,
217+
Arrays.asList(
218+
GridValue.createUnitValue(new UnitValue(1, 500.0f)),
219+
GridValue.createUnitValue(new UnitValue(1, 500.0f)),
220+
GridValue.createUnitValue(new UnitValue(1, 500.0f))));
221+
222+
gridcontainer0.add(new Image(ImageDataFactory.create(SOURCE_FOLDER + "rock_texture.jpg")).setHeight(150));
223+
document.add(gridcontainer0);
224+
225+
document.close();
226+
227+
Assert.assertNull(new CompareTool().compareByContent(fileName, SOURCE_FOLDER + "cmp_overflowGridContainer.pdf",
228+
DESTINATION_FOLDER, "diff"));
229+
}
230+
231+
@Test
232+
@LogMessages(messages = {
233+
@LogMessage(messageTemplate = LayoutLogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, logLevel =
234+
LogLevelConstants.WARN)})
235+
public void nothingResultTest() throws IOException, InterruptedException {
236+
String fileName = DESTINATION_FOLDER + "nothingResult.pdf";
237+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(fileName));
238+
Document document = new Document(pdfDocument);
239+
240+
GridContainer gridcontainer = new GridContainer();
241+
gridcontainer.add(new Image(ImageDataFactory.create(SOURCE_FOLDER + "rock_texture.jpg")).setHeight(1200));
242+
document.add(gridcontainer);
243+
244+
document.close();
220245

246+
Assert.assertNull(new CompareTool().compareByContent(fileName, SOURCE_FOLDER + "cmp_nothingResult.pdf",
247+
DESTINATION_FOLDER, "diff"));
221248
}
222249

223250
private GridContainer createGridBoxWithText() {
@@ -289,6 +316,4 @@ private GridContainer createGridBoxWithText() {
289316
gridcontainer0.add(div13);
290317
return gridcontainer0;
291318
}
292-
293-
294319
}

0 commit comments

Comments
 (0)