Skip to content

Commit 58f1e50

Browse files
author
Eugene Bochilo
committed
Support justify-content and align-items
DEVSIX-5040
1 parent 6328d38 commit 58f1e50

File tree

108 files changed

+979
-270
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+979
-270
lines changed

layout/src/main/java/com/itextpdf/layout/property/AlignmentPropertyValue.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,18 @@ This file is part of the iText (R) project.
4343
package com.itextpdf.layout.property;
4444

4545
/**
46-
* A specialized enum containing potential property values for {@link com.itextpdf.layout.property.Property#ALIGN_SELF}.
46+
* A specialized enum containing potential property values for {@link com.itextpdf.layout.property.Property#ALIGN_ITEMS}
47+
* and {@link com.itextpdf.layout.property.Property#ALIGN_SELF}.
4748
*/
4849
public enum AlignmentPropertyValue {
50+
CENTER,
51+
START,
52+
END,
53+
SELF_START,
54+
SELF_END,
4955
FLEX_START,
5056
FLEX_END,
51-
CENTER,
5257
BASELINE,
53-
STRETCH
58+
STRETCH,
59+
NORMAL,
5460
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.itextpdf.layout.property;
2+
3+
/**
4+
* A enum containing potential property values for {@link com.itextpdf.layout.property.Property#JUSTIFY_CONTENT}.
5+
*/
6+
public enum JustifyContent {
7+
CENTER,
8+
START,
9+
END,
10+
SELF_START,
11+
SELF_END,
12+
FLEX_START,
13+
FLEX_END,
14+
LEFT,
15+
RIGHT,
16+
NORMAL
17+
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2650,7 +2650,11 @@ IRenderer setChildRenderer(int index, IRenderer child) {
26502650
return removedElement;
26512651
}
26522652

2653-
private void setThisAsParent(Collection<IRenderer> children) {
2653+
/**
2654+
* Sets current {@link AbstractRenderer} as parent to renderers in specified collection.
2655+
* @param children the collection of renderers to set the parent renderer on
2656+
*/
2657+
void setThisAsParent(Collection<IRenderer> children) {
26542658
for (final IRenderer child : children) {
26552659
child.setParent(this);
26562660
}

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,13 @@ public LayoutResult layout(LayoutContext layoutContext) {
231231
if (marginsCollapsingEnabled) {
232232
childMarginsInfo = marginsCollapseHandler.startChildMarginsHandling(childRenderer, layoutBox);
233233
}
234-
while ((result = childRenderer.setParent(this).layout(new LayoutContext(new LayoutArea(pageNumber, layoutBox), childMarginsInfo, floatRendererAreas, wasHeightClipped || wasParentsHeightClipped)))
234+
Rectangle changedLayoutBox =
235+
recalculateLayoutBoxBeforeChildLayout(layoutBox, childRenderer, areas.get(0).clone());
236+
while ((result = childRenderer.setParent(this).layout(new LayoutContext(
237+
new LayoutArea(pageNumber, changedLayoutBox),
238+
childMarginsInfo,
239+
floatRendererAreas,
240+
wasHeightClipped || wasParentsHeightClipped)))
235241
.getStatus() != LayoutResult.FULL) {
236242

237243
if (Boolean.TRUE.equals(getPropertyAsBoolean(Property.FILL_AVAILABLE_AREA_ON_SPLIT))
@@ -319,7 +325,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
319325

320326
// The second condition check (after &&) is needed only if margins collapsing is enabled
321327
if (result.getOccupiedArea() != null && (!FloatingHelper.isRendererFloating(childRenderer) || includeFloatsInOccupiedArea)) {
322-
occupiedArea.setBBox(Rectangle.getCommonRectangle(occupiedArea.getBBox(), result.getOccupiedArea().getBBox()));
328+
recalculateOccupiedAreaAfterChildLayout(result);
323329
fixOccupiedAreaIfOverflowedX(overflowX, layoutBox);
324330
}
325331
if (marginsCollapsingEnabled) {
@@ -578,6 +584,15 @@ protected AbstractRenderer createOverflowRenderer(int layoutResult) {
578584
return overflowRenderer;
579585
}
580586

587+
void recalculateOccupiedAreaAfterChildLayout(LayoutResult result) {
588+
occupiedArea.setBBox(Rectangle.getCommonRectangle(occupiedArea.getBBox(), result.getOccupiedArea().getBBox()));
589+
}
590+
591+
Rectangle recalculateLayoutBoxBeforeChildLayout(Rectangle layoutBox,
592+
IRenderer childRenderer, Rectangle initialLayoutBox) {
593+
return layoutBox;
594+
}
595+
581596
AbstractRenderer[] createSplitAndOverflowRenderers(int childPos, int layoutStatus, LayoutResult childResult,
582597
Map<Integer, IRenderer> waitingFloatsSplitRenderers,
583598
List<IRenderer> waitingOverflowFloatRenderers) {

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

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -84,29 +84,17 @@ public IRenderer getNextRenderer() {
8484
@Override
8585
public LayoutResult layout(LayoutContext layoutContext) {
8686
Rectangle layoutContextRectangle = layoutContext.getArea().getBBox();
87-
for (final IRenderer childRenderer : this.getChildRenderers()) {
88-
if (childRenderer instanceof AbstractRenderer) {
89-
final AbstractRenderer abstractChildRenderer = (AbstractRenderer) childRenderer;
90-
abstractChildRenderer.setParent(this);
91-
}
92-
}
93-
Float containerWidth = retrieveWidth(layoutContextRectangle.getWidth());
94-
if (containerWidth == null) {
95-
containerWidth = layoutContextRectangle.getWidth();
96-
}
97-
Float containerHeight = retrieveHeight();
98-
if (containerHeight == null) {
99-
containerHeight = layoutContextRectangle.getHeight();
100-
}
101-
lines = FlexUtil.calculateChildrenRectangles(
102-
new Rectangle((float) containerWidth, (float) containerHeight), this);
87+
setThisAsParent(getChildRenderers());
88+
lines = FlexUtil.calculateChildrenRectangles(layoutContextRectangle, this);
10389
final List<UnitValue> previousWidths = new ArrayList<>();
90+
final List<UnitValue> previousHeights = new ArrayList<>();
10491
for (final List<FlexItemInfo> line : lines) {
10592
for (final FlexItemInfo itemInfo : line) {
10693
final Rectangle rectangleWithoutBordersMarginsPaddings =
10794
itemInfo.getRenderer().applyMarginsBordersPaddings(itemInfo.getRectangle().clone(), false);
10895

10996
previousWidths.add(itemInfo.getRenderer().<UnitValue>getProperty(Property.WIDTH));
97+
previousHeights.add(itemInfo.getRenderer().<UnitValue>getProperty(Property.HEIGHT));
11098

11199
itemInfo.getRenderer().setProperty(Property.WIDTH,
112100
UnitValue.createPointValue(rectangleWithoutBordersMarginsPaddings.getWidth()));
@@ -123,6 +111,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
123111
for (final List<FlexItemInfo> line : lines) {
124112
for (final FlexItemInfo itemInfo : line) {
125113
itemInfo.getRenderer().setProperty(Property.WIDTH, previousWidths.get(counter));
114+
itemInfo.getRenderer().setProperty(Property.HEIGHT, previousHeights.get(counter));
126115
++counter;
127116
}
128117
}
@@ -171,19 +160,17 @@ AbstractRenderer[] createSplitAndOverflowRenderers(int childPos, int layoutStatu
171160
List<IRenderer> waitingOverflowFloatRenderers) {
172161
final AbstractRenderer splitRenderer = createSplitRenderer(layoutStatus);
173162
final AbstractRenderer overflowRenderer = createOverflowRenderer(layoutStatus);
174-
final IRenderer childRenderer = childRenderers.get(childPos);
163+
final IRenderer childRenderer = getChildRenderers().get(childPos);
175164
final boolean forcedPlacement = Boolean.TRUE.equals(this.<Boolean>getProperty(Property.FORCED_PLACEMENT));
176165
boolean metChildRenderer = false;
177166
for (final List<FlexItemInfo> line : lines) {
178167
metChildRenderer = metChildRenderer ||
179168
line.stream().anyMatch(flexItem -> flexItem.getRenderer() == childRenderer);
180169
for (final FlexItemInfo itemInfo : line) {
181170
if (metChildRenderer && !forcedPlacement) {
182-
overflowRenderer.childRenderers.add(itemInfo.getRenderer());
183-
itemInfo.getRenderer().setParent(overflowRenderer);
171+
overflowRenderer.addChildRenderer(itemInfo.getRenderer());
184172
} else {
185-
splitRenderer.childRenderers.add(itemInfo.getRenderer());
186-
itemInfo.getRenderer().setParent(splitRenderer);
173+
splitRenderer.addChildRenderer(itemInfo.getRenderer());
187174
}
188175
}
189176
}
@@ -220,8 +207,7 @@ LayoutResult processNotFullChildResult(LayoutContext layoutContext,
220207

221208
if (keepTogether) {
222209
splitRenderer = null;
223-
overflowRenderer.childRenderers.clear();
224-
overflowRenderer.childRenderers = new ArrayList<>(childRenderers);
210+
overflowRenderer.setChildRenderers(getChildRenderers());
225211
}
226212

227213
correctFixedLayout(layoutBox);
@@ -230,17 +216,14 @@ LayoutResult processNotFullChildResult(LayoutContext layoutContext,
230216

231217
if (Boolean.TRUE.equals(getPropertyAsBoolean(Property.FORCED_PLACEMENT)) || wasHeightClipped) {
232218
if (splitRenderer != null) {
233-
splitRenderer.childRenderers = new ArrayList<>(childRenderers);
234-
for (final IRenderer childRenderer : splitRenderer.childRenderers) {
235-
childRenderer.setParent(splitRenderer);
236-
}
219+
splitRenderer.setChildRenderers(getChildRenderers());
237220
}
238221
return new LayoutResult(LayoutResult.FULL, result.getOccupiedArea(), splitRenderer, null, null);
239222
} else {
240223
applyPaddings(occupiedArea.getBBox(), paddings, true);
241224
applyBorderBox(occupiedArea.getBBox(), borders, true);
242225
applyMargins(occupiedArea.getBBox(), true);
243-
if (splitRenderer == null || splitRenderer.childRenderers.isEmpty()) {
226+
if (splitRenderer == null || splitRenderer.getChildRenderers().isEmpty()) {
244227
return new LayoutResult(LayoutResult.NOTHING, null, null, overflowRenderer,
245228
result.getCauseOfNothing()).setAreaBreak(result.getAreaBreak());
246229
} else {
@@ -255,18 +238,55 @@ boolean stopLayoutingChildrenIfChildResultNotFull(LayoutResult returnResult) {
255238
return returnResult.getStatus() != LayoutResult.FULL;
256239
}
257240

241+
@Override
242+
void recalculateOccupiedAreaAfterChildLayout(LayoutResult result) {
243+
// TODO DEVSIX-5098 Occupied area shall not be bigger than width or max-width
244+
Rectangle recalculatedRectangle =
245+
Rectangle.getCommonRectangle(occupiedArea.getBBox(), result.getOccupiedArea().getBBox());
246+
occupiedArea.getBBox().setY(recalculatedRectangle.getY());
247+
occupiedArea.getBBox().setHeight(recalculatedRectangle.getHeight());
248+
}
249+
258250
@Override
259251
void decreaseLayoutBoxAfterChildPlacement(Rectangle layoutBox, LayoutResult result, IRenderer childRenderer) {
260252
// TODO DEVSIX-5086 When flex-wrap will be fully supported
261253
// we'll need to decrease layout box with respect to the lines
262-
layoutBox.decreaseWidth(result.getOccupiedArea().getBBox().getWidth());
263-
layoutBox.moveRight(result.getOccupiedArea().getBBox().getWidth());
254+
layoutBox.decreaseWidth(result.getOccupiedArea().getBBox().getRight() - layoutBox.getLeft());
255+
layoutBox.setX(result.getOccupiedArea().getBBox().getRight());
256+
}
257+
258+
@Override
259+
Rectangle recalculateLayoutBoxBeforeChildLayout(Rectangle layoutBox,
260+
IRenderer childRenderer, Rectangle initialLayoutBox) {
261+
Rectangle layoutBoxCopy = layoutBox.clone();
262+
if (childRenderer instanceof AbstractRenderer) {
263+
FlexItemInfo childFlexItemInfo = findFlexItemInfo((AbstractRenderer) childRenderer);
264+
if (childFlexItemInfo != null) {
265+
layoutBoxCopy.decreaseWidth(childFlexItemInfo.getRectangle().getX());
266+
layoutBoxCopy.moveRight(childFlexItemInfo.getRectangle().getX());
267+
268+
layoutBoxCopy.decreaseHeight(childFlexItemInfo.getRectangle().getY());
269+
}
270+
}
271+
return layoutBoxCopy;
272+
}
273+
274+
private FlexItemInfo findFlexItemInfo(AbstractRenderer renderer) {
275+
for (List<FlexItemInfo> line : lines) {
276+
for (FlexItemInfo itemInfo : line) {
277+
if (itemInfo.getRenderer().equals(renderer)) {
278+
return itemInfo;
279+
}
280+
}
281+
}
282+
return null;
264283
}
265284

266285
private void findMinMaxWidthIfCorrespondingPropertiesAreNotSet(MinMaxWidth minMaxWidth,
267286
AbstractWidthHandler minMaxWidthHandler) {
268287
// TODO DEVSIX-5086 When flex-wrap will be fully supported we'll find min/max width with respect to the lines
269-
for (final IRenderer childRenderer : childRenderers) {
288+
setThisAsParent(getChildRenderers());
289+
for (final IRenderer childRenderer : getChildRenderers()) {
270290
MinMaxWidth childMinMaxWidth;
271291
childRenderer.setParent(this);
272292
if (childRenderer instanceof AbstractRenderer) {

0 commit comments

Comments
 (0)