Skip to content

Commit

Permalink
Improve LayoutResult.NOTHING processing of the cells and a container…
Browse files Browse the repository at this point in the history
… itself, add proper forced placement logic

DEVSIX-8329

Autoported commit.
Original commit hash: [d00b4cf18]
  • Loading branch information
vitali-pr committed May 29, 2024
1 parent 827ffe9 commit 2de8c47
Show file tree
Hide file tree
Showing 17 changed files with 71 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ public virtual void ThreeColumnsWithSquareCellAndCellWithExplicitHeightTest() {
templateColumns.Add(GridValue.CreateUnitValue(new UnitValue(UnitValue.POINT, 100.0f)));
using (Document document = new Document(new PdfDocument(new PdfWriter(filename)))) {
GridContainer grid = new GridContainer();
grid.SetBackgroundColor(ColorConstants.GREEN);
SolidBorder border = new SolidBorder(ColorConstants.BLUE, 1);
grid.SetProperty(Property.GRID_TEMPLATE_COLUMNS, templateColumns);
Paragraph paragraph1 = new Paragraph("One");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ You should have received a copy of the GNU Affero General Public License
using iText.Layout;
using iText.Layout.Borders;
using iText.Layout.Element;
using iText.Layout.Logs;
using iText.Layout.Properties;
using iText.Test;
using iText.Test.Attributes;

namespace iText.Layout.Element.Gridcontainer {
[NUnit.Framework.Category("IntegrationTest")]
Expand Down Expand Up @@ -156,23 +158,38 @@ public virtual void EmptyGridContainerTest() {
, DESTINATION_FOLDER, "diff"));
}

private GridContainer CreateGridBoxWithSizedDiv() {
GridContainer gridcontainer0 = new GridContainer();
gridcontainer0.SetProperty(Property.COLUMN_GAP_BORDER, null);
gridcontainer0.SetProperty(Property.GRID_TEMPLATE_COLUMNS, JavaUtil.ArraysAsList(new UnitValue(1, 150.0f),
new UnitValue(1, 150.0f), new UnitValue(1, 150.0f)));
gridcontainer0.SetProperty(Property.COLUMN_GAP, 12.0f);
gridcontainer0.SetBackgroundColor(ColorConstants.RED);
for (int i = 0; i < 4; i++) {
Div div1 = new Div();
div1.SetBackgroundColor(ColorConstants.YELLOW);
div1.SetHeight(20);
div1.SetWidth(30);
div1.SetProperty(Property.COLUMN_GAP_BORDER, null);
div1.SetProperty(Property.COLUMN_GAP, 12.0f);
gridcontainer0.Add(div1);
}
return gridcontainer0;
// TODO DEVSIX-8340
[NUnit.Framework.Test]
public virtual void OverflowGridContainerTest() {
String fileName = DESTINATION_FOLDER + "overflowGridContainer.pdf";
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(fileName));
Document document = new Document(pdfDocument);
GridContainer gridcontainer0 = CreateGridBoxWithText();
gridcontainer0.SetBackgroundColor(ColorConstants.MAGENTA);
gridcontainer0.SetProperty(Property.GRID_TEMPLATE_ROWS, JavaUtil.ArraysAsList(GridValue.CreateUnitValue(new
UnitValue(1, 500.0f)), GridValue.CreateUnitValue(new UnitValue(1, 500.0f)), GridValue.CreateUnitValue(
new UnitValue(1, 500.0f))));
gridcontainer0.Add(new iText.Layout.Element.Image(ImageDataFactory.Create(SOURCE_FOLDER + "rock_texture.jpg"
)).SetHeight(150));
document.Add(gridcontainer0);
document.Close();
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(fileName, SOURCE_FOLDER + "cmp_overflowGridContainer.pdf"
, DESTINATION_FOLDER, "diff"));
}

[NUnit.Framework.Test]
[LogMessage(LayoutLogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, LogLevel = LogLevelConstants.WARN)]
public virtual void NothingResultTest() {
String fileName = DESTINATION_FOLDER + "nothingResult.pdf";
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(fileName));
Document document = new Document(pdfDocument);
GridContainer gridcontainer = new GridContainer();
gridcontainer.Add(new iText.Layout.Element.Image(ImageDataFactory.Create(SOURCE_FOLDER + "rock_texture.jpg"
)).SetHeight(1200));
document.Add(gridcontainer);
document.Close();
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(fileName, SOURCE_FOLDER + "cmp_nothingResult.pdf"
, DESTINATION_FOLDER, "diff"));
}

private GridContainer CreateGridBoxWithText() {
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
77 changes: 35 additions & 42 deletions itext/itext.layout/itext/layout/renderer/GridContainerRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,45 +67,33 @@ public override LayoutResult Layout(LayoutContext layoutContext) {
ApplyMargins(actualBBox, false);
Grid grid = ConstructGrid(this, actualBBox);
GridContainerRenderer.GridLayoutResult layoutResult = LayoutGrid(layoutContext, actualBBox, grid);
//TODO DEVSIX-8329 improve nothing processing, consider checking for cause of nothing here?
//TODO DEVSIX-8329 improve forced placement logic
if (layoutResult.GetOverflowRenderers().IsEmpty() && layoutResult.GetSplitRenderers().IsEmpty()) {
if (layoutResult.GetOverflowRenderers().IsEmpty()) {
this.occupiedArea = CalculateContainerOccupiedArea(layoutContext, grid, true);
return new LayoutResult(LayoutResult.FULL, this.occupiedArea, null, null);
}
else {
if (layoutResult.GetSplitRenderers().IsEmpty()) {
if (true.Equals(this.GetProperty<bool?>(Property.FORCED_PLACEMENT))) {
this.occupiedArea = CalculateContainerOccupiedArea(layoutContext, grid, true);
return new LayoutResult(LayoutResult.FULL, this.occupiedArea, this, null);
}
IRenderer cause = this;
if (!layoutResult.GetCauseOfNothing().IsEmpty()) {
cause = layoutResult.GetCauseOfNothing()[0];
}
return new LayoutResult(LayoutResult.NOTHING, null, null, this, cause);
}
else {
if (layoutResult.GetOverflowRenderers().IsEmpty()) {
ContinuousContainer continuousContainer = this.GetProperty<ContinuousContainer>(Property.TREAT_AS_CONTINUOUS_CONTAINER_RESULT
);
if (continuousContainer != null) {
continuousContainer.ReApplyProperties(this);
}
this.childRenderers.Clear();
this.AddAllChildRenderers(layoutResult.GetSplitRenderers());
this.occupiedArea = CalculateContainerOccupiedArea(layoutContext, grid, true);
return new LayoutResult(LayoutResult.FULL, this.occupiedArea, this, null);
}
else {
this.occupiedArea = CalculateContainerOccupiedArea(layoutContext, grid, false);
return new LayoutResult(LayoutResult.PARTIAL, this.occupiedArea, CreateSplitRenderer(layoutResult.GetSplitRenderers
()), CreateOverflowRenderer(layoutResult.GetOverflowRenderers()));
}
this.occupiedArea = CalculateContainerOccupiedArea(layoutContext, grid, false);
return new LayoutResult(LayoutResult.PARTIAL, this.occupiedArea, CreateSplitRenderer(layoutResult.GetSplitRenderers
()), CreateOverflowRenderer(layoutResult.GetOverflowRenderers()));
}
}
}

/// <summary><inheritDoc/></summary>
public override void AddChild(IRenderer renderer) {
renderer.SetProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE);
renderer.SetProperty(Property.OVERFLOW_Y, OverflowPropertyValue.VISIBLE);
base.AddChild(renderer);
}

private AbstractRenderer CreateSplitRenderer(IList<IRenderer> children) {
AbstractRenderer splitRenderer = (AbstractRenderer)GetNextRenderer();
splitRenderer.parent = parent;
Expand All @@ -119,6 +107,7 @@ private AbstractRenderer CreateSplitRenderer(IList<IRenderer> children) {
}

private AbstractRenderer CreateOverflowRenderer(IList<IRenderer> children) {
// TODO DEVSIX-8340 - We put the original amount of rows into overflow container.
iText.Layout.Renderer.GridContainerRenderer overflowRenderer = (iText.Layout.Renderer.GridContainerRenderer
)GetNextRenderer();
overflowRenderer.isFirstLayout = false;
Expand All @@ -135,29 +124,33 @@ private GridContainerRenderer.GridLayoutResult LayoutGrid(LayoutContext layoutCo
, Grid grid) {
GridContainerRenderer.GridLayoutResult layoutResult = new GridContainerRenderer.GridLayoutResult();
EnsureTemplateValuesFit(grid, actualBBox);
//TODO DEVSIX-8329 improve forced placement logic, right now if we have a cell which could not be fitted on its
// area or returns nothing as layout result RootRenderer sets FORCED_PLACEMENT on this class instance.
// And basically every cell inherits this value and force placed, but we only need to force place cells
// which were not fitted originally.
foreach (GridCell cell in grid.GetUniqueGridCells(Grid.GridOrder.ROW)) {
//If cell couldn't fit during cell layout area calculation than we need to put such cell straight to
//nothing result list
if (!cell.IsValueFitOnCellArea()) {
layoutResult.GetOverflowRenderers().Add(cell.GetValue());
layoutResult.GetCauseOfNothing().Add(cell.GetValue());
continue;
}
//Calculate cell layout context by getting actual x and y on parent layout area for it
// Calculate cell layout context by getting actual x and y on parent layout area for it
LayoutContext cellContext = GetCellLayoutContext(layoutContext, actualBBox, cell);
//We need to check for forced placement here, because otherwise we would infinitely return partial result.
if (!true.Equals(this.GetProperty<bool?>(Property.FORCED_PLACEMENT)) && !actualBBox.Contains(cellContext.GetArea
().GetBBox())) {
layoutResult.GetOverflowRenderers().Add(cell.GetValue());
continue;
}
IRenderer cellToRender = cell.GetValue();
cellToRender.SetProperty(Property.FILL_AVAILABLE_AREA, true);
cellToRender.SetProperty(Property.COLLAPSING_MARGINS, false);
// Now set the height for the individual items
// We know cell height upfront and this way we tell the element what it can occupy
Rectangle cellBBox = cellContext.GetArea().GetBBox();
if (!cellToRender.HasProperty(Property.HEIGHT)) {
Rectangle rectangleWithoutBordersMarginsPaddings = cellBBox.Clone();
if (cellToRender is AbstractRenderer) {
AbstractRenderer abstractCellRenderer = ((AbstractRenderer)cellToRender);
// We subtract margins/borders/paddings because we should take into account that
// borders/paddings/margins should also fit into a cell.
if (AbstractRenderer.IsBorderBoxSizing(cellToRender)) {
abstractCellRenderer.ApplyMargins(rectangleWithoutBordersMarginsPaddings, false);
}
else {
abstractCellRenderer.ApplyMarginsBordersPaddings(rectangleWithoutBordersMarginsPaddings, false);
}
}
cellToRender.SetProperty(Property.HEIGHT, UnitValue.CreatePointValue(rectangleWithoutBordersMarginsPaddings
.GetHeight()));
}
// Adjust cell BBox to the remaining part of the layout bbox
// This way we can layout elements partially
cellBBox.SetHeight(cellBBox.GetTop() - actualBBox.GetBottom()).SetY(actualBBox.GetY());
LayoutResult cellResult = cellToRender.Layout(cellContext);
if (cellResult.GetStatus() == LayoutResult.NOTHING) {
layoutResult.GetOverflowRenderers().Add(cellToRender);
Expand Down
2 changes: 1 addition & 1 deletion port-hash
Original file line number Diff line number Diff line change
@@ -1 +1 @@
098c8d1be92b86d5047479ae644b040ac5c96496
01634ed53f0c7250cf60680823296606cdafb0e2

0 comments on commit 2de8c47

Please sign in to comment.