@@ -136,6 +136,7 @@ public LayoutResult layout(LayoutContext layoutContext) {
136136 UnitValue .createPointValue (rectangleWithoutBordersMarginsPaddings .getHeight ()));
137137 }
138138 }
139+
139140 final LayoutResult result = super .layout (layoutContext );
140141
141142 // We must set back widths of the children because multiple layouts are possible
@@ -195,17 +196,25 @@ AbstractRenderer[] createSplitAndOverflowRenderers(int childPos, int layoutStatu
195196 List <IRenderer > waitingOverflowFloatRenderers ) {
196197 final AbstractRenderer splitRenderer = createSplitRenderer (layoutStatus );
197198 final AbstractRenderer overflowRenderer = createOverflowRenderer (layoutStatus );
199+
198200 final IRenderer childRenderer = getChildRenderers ().get (childPos );
199201 final boolean forcedPlacement = Boolean .TRUE .equals (this .<Boolean >getProperty (Property .FORCED_PLACEMENT ));
200202 boolean metChildRenderer = false ;
201203 for (final List <FlexItemInfo > line : lines ) {
202- metChildRenderer = metChildRenderer ||
203- line .stream ().anyMatch (flexItem -> flexItem .getRenderer () == childRenderer );
204- for (final FlexItemInfo itemInfo : line ) {
205- if (metChildRenderer && !forcedPlacement ) {
206- overflowRenderer .addChildRenderer (itemInfo .getRenderer ());
207- } else {
208- splitRenderer .addChildRenderer (itemInfo .getRenderer ());
204+ final boolean isSplitLine = line .stream ().anyMatch (flexItem -> flexItem .getRenderer () == childRenderer );
205+ metChildRenderer = metChildRenderer || isSplitLine ;
206+
207+ // If the renderer to split is in the current line
208+ if (isSplitLine && !forcedPlacement && layoutStatus == LayoutResult .PARTIAL ) {
209+ fillSplitOverflowRenderersForPartialResult (splitRenderer , overflowRenderer , line , childRenderer ,
210+ childResult );
211+ } else {
212+ for (final FlexItemInfo itemInfo : line ) {
213+ if (metChildRenderer && !forcedPlacement ) {
214+ overflowRenderer .addChildRenderer (itemInfo .getRenderer ());
215+ } else {
216+ splitRenderer .addChildRenderer (itemInfo .getRenderer ());
217+ }
209218 }
210219 }
211220 }
@@ -224,22 +233,30 @@ LayoutResult processNotFullChildResult(LayoutContext layoutContext,
224233 List <Rectangle > areas , int currentAreaPos , Rectangle layoutBox ,
225234 Set <Rectangle > nonChildFloatingRendererAreas , IRenderer causeOfNothing ,
226235 boolean anythingPlaced , int childPos , LayoutResult result ) {
227-
228236 final boolean keepTogether = isKeepTogether (causeOfNothing );
237+ if (Boolean .TRUE .equals (getPropertyAsBoolean (Property .FORCED_PLACEMENT )) || wasHeightClipped ) {
238+ final AbstractRenderer splitRenderer = keepTogether ? null : createSplitRenderer (result .getStatus ());
239+ if (splitRenderer != null ) {
240+ splitRenderer .setChildRenderers (getChildRenderers ());
241+ }
242+
243+ return new LayoutResult (LayoutResult .FULL ,
244+ getOccupiedAreaInCaseNothingWasWrappedWithFull (result , splitRenderer ), splitRenderer , null , null );
245+ }
229246
230247 final AbstractRenderer [] splitAndOverflowRenderers = createSplitAndOverflowRenderers (
231248 childPos , result .getStatus (), result , waitingFloatsSplitRenderers , waitingOverflowFloatRenderers );
232249
233250 AbstractRenderer splitRenderer = splitAndOverflowRenderers [0 ];
234251 final AbstractRenderer overflowRenderer = splitAndOverflowRenderers [1 ];
235252 overflowRenderer .deleteOwnProperty (Property .FORCED_PLACEMENT );
253+ updateHeightsOnSplit (wasHeightClipped , splitRenderer , overflowRenderer );
236254
237255 if (isRelativePosition () && !positionedRenderers .isEmpty ()) {
238256 overflowRenderer .positionedRenderers = new ArrayList <>(positionedRenderers );
239257 }
240258
241259 // TODO DEVSIX-5086 When flex-wrap will be fully supported we'll need to update height on split
242-
243260 if (keepTogether ) {
244261 splitRenderer = null ;
245262 overflowRenderer .setChildRenderers (getChildRenderers ());
@@ -249,23 +266,15 @@ LayoutResult processNotFullChildResult(LayoutContext layoutContext,
249266
250267 applyAbsolutePositionIfNeeded (layoutContext );
251268
252- if ( Boolean . TRUE . equals ( getPropertyAsBoolean ( Property . FORCED_PLACEMENT )) || wasHeightClipped ) {
253- if ( splitRenderer != null ) {
254- splitRenderer . setChildRenderers ( getChildRenderers () );
255- }
256- return new LayoutResult (LayoutResult .FULL ,
257- getOccupiedAreaInCaseNothingWasWrappedWithFull ( result , splitRenderer ), splitRenderer , null , null );
269+ applyPaddings ( occupiedArea . getBBox (), paddings , true );
270+ applyBorderBox ( occupiedArea . getBBox (), borders , true );
271+ applyMargins ( occupiedArea . getBBox (), true );
272+ if ( splitRenderer == null || splitRenderer . getChildRenderers (). isEmpty ()) {
273+ return new LayoutResult (LayoutResult .NOTHING , null , null , overflowRenderer ,
274+ result . getCauseOfNothing ()). setAreaBreak ( result . getAreaBreak () );
258275 } else {
259- applyPaddings (occupiedArea .getBBox (), paddings , true );
260- applyBorderBox (occupiedArea .getBBox (), borders , true );
261- applyMargins (occupiedArea .getBBox (), true );
262- if (splitRenderer == null || splitRenderer .getChildRenderers ().isEmpty ()) {
263- return new LayoutResult (LayoutResult .NOTHING , null , null , overflowRenderer ,
264- result .getCauseOfNothing ()).setAreaBreak (result .getAreaBreak ());
265- } else {
266- return new LayoutResult (LayoutResult .PARTIAL , layoutContext .getArea (), splitRenderer ,
267- overflowRenderer , null ).setAreaBreak (result .getAreaBreak ());
268- }
276+ return new LayoutResult (LayoutResult .PARTIAL , layoutContext .getArea (), splitRenderer ,
277+ overflowRenderer , null ).setAreaBreak (result .getAreaBreak ());
269278 }
270279 }
271280
@@ -354,7 +363,7 @@ private FlexItemInfo findFlexItemInfo(AbstractRenderer renderer) {
354363 }
355364 return null ;
356365 }
357-
366+
358367 @ Override
359368 void fixOccupiedAreaIfOverflowedX (OverflowPropertyValue overflowX , Rectangle layoutBox ) {
360369 // TODO DEVSIX-5087 Support overflow visible/hidden property correctly
@@ -373,6 +382,71 @@ public void addChild(IRenderer renderer) {
373382 super .addChild (renderer );
374383 }
375384
385+ private void fillSplitOverflowRenderersForPartialResult (AbstractRenderer splitRenderer ,
386+ AbstractRenderer overflowRenderer , List <FlexItemInfo > line , IRenderer childRenderer ,
387+ LayoutResult childResult ) {
388+ // If we split, we remove (override) Property.ALIGN_ITEMS for the overflow renderer.
389+ // because we have to layout the remaining part at the top of the layout context.
390+ // TODO DEVSIX-5086 When flex-wrap will be fully supported we'll need to reconsider this.
391+ // The question is what should be set/calculated for the next line
392+ overflowRenderer .setProperty (Property .ALIGN_ITEMS , null );
393+
394+ float occupiedSpace = 0 ;
395+ boolean metChildRendererInLine = false ;
396+ for (final FlexItemInfo itemInfo : line ) {
397+ // Split the line
398+ if (itemInfo .getRenderer () == childRenderer ) {
399+ metChildRendererInLine = true ;
400+ if (childResult .getSplitRenderer () != null ) {
401+ splitRenderer .addChildRenderer (childResult .getSplitRenderer ());
402+ }
403+
404+ if (childResult .getOverflowRenderer () != null ) {
405+ overflowRenderer .addChildRenderer (childResult .getOverflowRenderer ());
406+ }
407+ } else if (metChildRendererInLine ) {
408+ // Process all following renderers in the current line
409+ // We have to layout them to understand what goes where
410+ final Rectangle neighbourBbox = getOccupiedAreaBBox ().clone ();
411+ // Move bbox by occupied space
412+ neighbourBbox .setX (neighbourBbox .getX () + occupiedSpace );
413+ neighbourBbox .setWidth (itemInfo .getRectangle ().getWidth ());
414+
415+ // Y of the renderer has been already calculated, move bbox accordingly
416+ neighbourBbox .setY (neighbourBbox .getY () - itemInfo .getRectangle ().getY ());
417+
418+ final LayoutResult neighbourLayoutResult = itemInfo .getRenderer ().layout (new LayoutContext (
419+ new LayoutArea (childResult .getOccupiedArea ().getPageNumber (), neighbourBbox )));
420+ // Handle result
421+ if (neighbourLayoutResult .getStatus () == LayoutResult .PARTIAL &&
422+ neighbourLayoutResult .getSplitRenderer () != null ) {
423+ splitRenderer .addChildRenderer (neighbourLayoutResult .getSplitRenderer ());
424+ } else if (neighbourLayoutResult .getStatus () == LayoutResult .FULL ) {
425+ splitRenderer .addChildRenderer (itemInfo .getRenderer ());
426+ } else {
427+ // LayoutResult.NOTHING
428+ }
429+
430+ if (neighbourLayoutResult .getOverflowRenderer () != null ) {
431+ overflowRenderer .addChildRenderer (neighbourLayoutResult .getOverflowRenderer ());
432+ } else {
433+ // Here we might need to still occupy the space on overflow renderer
434+ addSimulateDiv (overflowRenderer , itemInfo .getRectangle ().getWidth ());
435+ }
436+ } else {
437+ // Process all preceeding renderers in the current line
438+ // They all were layouted as FULL so add them into split renderer
439+ splitRenderer .addChildRenderer (itemInfo .getRenderer ());
440+
441+ // But we also need to occupy the space on overflow renderer
442+ addSimulateDiv (overflowRenderer , itemInfo .getRectangle ().getWidth ());
443+ }
444+
445+ // X is nonzero only for the 1st renderer in line serving for alignment adjustments
446+ occupiedSpace += itemInfo .getRectangle ().getX () + itemInfo .getRectangle ().getWidth ();
447+ }
448+ }
449+
376450 private void findMinMaxWidthIfCorrespondingPropertiesAreNotSet (MinMaxWidth minMaxWidth ,
377451 AbstractWidthHandler minMaxWidthHandler ) {
378452 // TODO DEVSIX-5086 When flex-wrap will be fully supported we'll find min/max width with respect to the lines
@@ -390,4 +464,9 @@ private void findMinMaxWidthIfCorrespondingPropertiesAreNotSet(MinMaxWidth minMa
390464 }
391465 }
392466
467+ private static void addSimulateDiv (AbstractRenderer overflowRenderer , float width ) {
468+ final IRenderer fakeOverflowRenderer = new DivRenderer (
469+ new Div ().setMinWidth (width ).setMaxWidth (width ));
470+ overflowRenderer .addChildRenderer (fakeOverflowRenderer );
471+ }
393472}
0 commit comments