|
@@ -120,12 +120,15 @@ type
|
|
|
|
|
|
protected
|
|
|
FLineItems: TFPList; // list of TLineItem
|
|
|
+ FAbsoluteItems: TFPList; // list of TLineItem
|
|
|
procedure PlaceLineItems; virtual;
|
|
|
function PlaceAbsoluteItem(ChildNode: TUsedLayoutNode; aMode: TFresnelLayoutMode;
|
|
|
aMaxWidth, aMaxHeight: TFresnelLength; const DefaultPos: TFresnelPoint;
|
|
|
Commit: boolean): TFresnelPoint; virtual;
|
|
|
- procedure ClearLineItems; virtual;
|
|
|
+ function AddAbsoluteItem(ChildNode: TUsedLayoutNode; NodeClass: TLineItemClass): TLineItem; virtual;
|
|
|
function AddLineItem(ChildNode: TUsedLayoutNode; NodeClass: TLineItemClass): TLineItem; virtual;
|
|
|
+ procedure ClearAbsoluteItems; virtual;
|
|
|
+ procedure ClearLineItems; virtual;
|
|
|
procedure ComputeChildAttributes(Item: TLineItem; El: TFresnelElement); virtual;
|
|
|
public
|
|
|
destructor Destroy; override;
|
|
@@ -146,14 +149,15 @@ type
|
|
|
protected
|
|
|
// current line
|
|
|
FLineBorderBoxHeight: TFresnelLength;
|
|
|
- FLineBorderBoxLeft: TFresnelLength; // border box of last element relative to parent ContentBox
|
|
|
+ FLineBorderBoxLeft: TFresnelLength; // border box position of last element relative to parent ContentBox
|
|
|
FLineBorderBoxRight: TFresnelLength;
|
|
|
FLineBorderBoxTop: TFresnelLength;
|
|
|
FLineBorderBoxBottom: TFresnelLength;
|
|
|
- FLineMarginLeft: TFresnelLength;
|
|
|
+ FLineMarginLeft: TFresnelLength; // margin width
|
|
|
FLineMarginRight: TFresnelLength;
|
|
|
FLineMarginTop: TFresnelLength;
|
|
|
FLineMarginBottom: TFresnelLength;
|
|
|
+ FLineFirstAbsoluteIndex: integer;
|
|
|
FLastLineBorderBoxBottom: TFresnelLength;
|
|
|
FLastLineMarginBottom: TFresnelLength;
|
|
|
procedure StartLine; virtual;
|
|
@@ -668,6 +672,10 @@ begin
|
|
|
end;
|
|
|
|
|
|
procedure TFLFlowLayouter.EndLine(Commit: boolean);
|
|
|
+var
|
|
|
+ Item: TLineItem;
|
|
|
+ El: TFresnelElement;
|
|
|
+ IsInline: Boolean;
|
|
|
begin
|
|
|
if FLineItems.Count=0 then
|
|
|
exit;
|
|
@@ -676,7 +684,22 @@ begin
|
|
|
FLineBorderBoxBottom:=FLineBorderBoxTop+FLineBorderBoxHeight;
|
|
|
|
|
|
if Commit then
|
|
|
+ begin
|
|
|
PlaceLineItems;
|
|
|
+ if FAbsoluteItems<>nil then
|
|
|
+ begin
|
|
|
+ // set default top position of absolute blocks below line
|
|
|
+ while FLineFirstAbsoluteIndex<FAbsoluteItems.Count do
|
|
|
+ begin
|
|
|
+ Item:=TLineItem(FAbsoluteItems[FLineFirstAbsoluteIndex]);
|
|
|
+ El:=Item.Node.Element;
|
|
|
+ IsInline:=El.ComputedDisplayOutside=CSSRegistry.kwInline;
|
|
|
+ if not IsInline then
|
|
|
+ Item.StaticTop:=FLineBorderBoxBottom+FLineMarginBottom;
|
|
|
+ inc(FLineFirstAbsoluteIndex);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
ClearLineItems;
|
|
|
|
|
|
FLastLineBorderBoxBottom:=FLineBorderBoxBottom;
|
|
@@ -746,8 +769,8 @@ function TFLFlowLayouter.ComputeLayoutContent(aMode: TFresnelLayoutMode; aMaxWid
|
|
|
aMaxHeight: TFresnelLength; Commit: boolean): TFresnelPoint;
|
|
|
var
|
|
|
ChildIndex: Integer;
|
|
|
- ChildNode, LastFlowNode: TUsedLayoutNode;
|
|
|
- ChildEl, LastFlowEl, El: TFresnelElement;
|
|
|
+ ChildNode: TUsedLayoutNode;
|
|
|
+ ChildEl, El: TFresnelElement;
|
|
|
IsInline: Boolean;
|
|
|
NewChildRight, CurSpace, OldMarginBoxBottom,
|
|
|
ChildMBoxLeft, ChildMBoxRight { MarginBox relative to parent ContentBox left },
|
|
@@ -757,6 +780,7 @@ var
|
|
|
ChildMarginLeft, ChildMarginRight, ChildMarginTop, ChildMarginBottom,
|
|
|
ChildPadBorderX, ChildPadBorderY: TFresnelLength;
|
|
|
ChildPrefSize, ChildDefPos: TFresnelPoint;
|
|
|
+ AbsItem: TLineItem;
|
|
|
|
|
|
procedure AddLineNodeCache;
|
|
|
var
|
|
@@ -786,6 +810,8 @@ begin
|
|
|
|
|
|
FLastLineBorderBoxBottom:=0;
|
|
|
FLastLineMarginBottom:=0;
|
|
|
+ FLineFirstAbsoluteIndex:=0;
|
|
|
+ ClearAbsoluteItems;
|
|
|
El:=Node.Element;
|
|
|
|
|
|
// add elements to the line until full
|
|
@@ -797,11 +823,23 @@ begin
|
|
|
|
|
|
if ChildNode.SkipLayout then continue;
|
|
|
|
|
|
+ IsInline:=ChildEl.ComputedDisplayOutside=CSSRegistry.kwInline;
|
|
|
+
|
|
|
// skip position: absolute and fixed
|
|
|
if ChildEl.ComputedPosition in [CSSRegistry.kwAbsolute,CSSRegistry.kwFixed] then
|
|
|
+ begin
|
|
|
+ if Commit then
|
|
|
+ begin
|
|
|
+ AbsItem:=AddAbsoluteItem(ChildNode,TLineItem);
|
|
|
+ if IsInline then
|
|
|
+ AbsItem.StaticLeft:=FLineBorderBoxRight+FLineMarginRight
|
|
|
+ else begin
|
|
|
+ AbsItem.StaticTop:=FLineBorderBoxTop-FLineMarginTop;
|
|
|
+ AbsItem.StaticLeft:=0;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
continue;
|
|
|
-
|
|
|
- IsInline:=ChildEl.ComputedDisplayOutside=CSSRegistry.kwInline;
|
|
|
+ end;
|
|
|
|
|
|
// display-outside: inline or block
|
|
|
if (not IsInline) or (aMode in [flmMinWidth,flmMaxHeight]) then
|
|
@@ -967,43 +1005,20 @@ begin
|
|
|
end;
|
|
|
EndLine(Commit);
|
|
|
|
|
|
- if Commit then
|
|
|
+ if Commit and (FAbsoluteItems<>nil) then
|
|
|
begin
|
|
|
// place absolute items
|
|
|
- LastFlowNode:=nil;
|
|
|
- for ChildIndex:=0 to El.NodeCount-1 do
|
|
|
+ for ChildIndex:=0 to FAbsoluteItems.Count-1 do
|
|
|
begin
|
|
|
- ChildEl:=El.Nodes[ChildIndex];
|
|
|
- ChildNode:=TUsedLayoutNode(ChildEl.LayoutNode);
|
|
|
+ AbsItem:=TLineItem(FAbsoluteItems[ChildIndex]);
|
|
|
+ ChildNode:=AbsItem.Node;
|
|
|
|
|
|
- if ChildNode.SkipLayout then continue;
|
|
|
+ ChildDefPos.X:=AbsItem.StaticLeft;
|
|
|
+ ChildDefPos.Y:=AbsItem.StaticTop;
|
|
|
|
|
|
- case ChildEl.ComputedPosition of
|
|
|
- CSSRegistry.kwStatic,CSSRegistry.kwRelative,CSSRegistry.kwSticky:
|
|
|
- LastFlowNode:=ChildNode;
|
|
|
- else
|
|
|
- // position is absolute or fixed
|
|
|
- IsInline:=ChildEl.ComputedDisplayOutside=CSSRegistry.kwInline;
|
|
|
- if LastFlowNode=nil then
|
|
|
- begin
|
|
|
- ChildDefPos.X:=0;
|
|
|
- ChildDefPos.Y:=0;
|
|
|
- end else if IsInline then
|
|
|
- begin
|
|
|
- // next inline position
|
|
|
- LastFlowEl:=LastFlowNode.Element;
|
|
|
- ChildDefPos.X:=LastFlowEl.UsedBorderBox.Right+LastFlowNode.MarginRight;
|
|
|
- ChildDefPos.Y:=LastFlowNode.Top;
|
|
|
- end else begin
|
|
|
- // next block position
|
|
|
- LastFlowEl:=LastFlowNode.Element;
|
|
|
- ChildDefPos.X:=0;
|
|
|
- ChildDefPos.Y:=LastFlowEl.UsedBorderBox.Bottom+LastFlowNode.MarginBottom; // todo: use actual line height
|
|
|
- end;
|
|
|
-
|
|
|
- PlaceAbsoluteItem(ChildNode,aMode,aMaxWidth,aMaxHeight,ChildDefPos,Commit);
|
|
|
- end;
|
|
|
+ PlaceAbsoluteItem(ChildNode,aMode,aMaxWidth,aMaxHeight,ChildDefPos,Commit);
|
|
|
end;
|
|
|
+ ClearAbsoluteItems;
|
|
|
end;
|
|
|
|
|
|
Result.Y:=Max(Result.Y,FLastLineBorderBoxBottom+FLastLineMarginBottom);
|
|
@@ -1484,7 +1499,7 @@ begin
|
|
|
|
|
|
if ChildNode.SkipLayout then continue;
|
|
|
|
|
|
- // skip position: absolute and fixed
|
|
|
+ // absolute and fixed: todo: place after items have their final static box
|
|
|
if ChildEl.ComputedPosition in [CSSRegistry.kwAbsolute,CSSRegistry.kwFixed] then
|
|
|
begin
|
|
|
ChildDefPos.X:=0;
|
|
@@ -1551,6 +1566,7 @@ begin
|
|
|
|
|
|
NewLeft:=Item.StaticLeft;
|
|
|
NewTop:=Item.StaticTop;
|
|
|
+
|
|
|
if ChildEl.ComputedPosition in [CSSRegistry.kwRelative,CSSRegistry.kwSticky] then
|
|
|
begin
|
|
|
// relative left
|
|
@@ -1725,6 +1741,27 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
+function TFLLineLayouter.AddLineItem(ChildNode: TUsedLayoutNode; NodeClass: TLineItemClass
|
|
|
+ ): TLineItem;
|
|
|
+begin
|
|
|
+ Result:=NodeClass.Create;
|
|
|
+ if FLineItems=nil then
|
|
|
+ FLineItems:=TFPList.Create;
|
|
|
+ FLineItems.Add(Result);
|
|
|
+ Result.Node:=ChildNode;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TFLLineLayouter.ClearAbsoluteItems;
|
|
|
+var
|
|
|
+ i: Integer;
|
|
|
+begin
|
|
|
+ if (FAbsoluteItems=nil) or (FAbsoluteItems.Count=0) then
|
|
|
+ exit;
|
|
|
+ for i:=0 to FAbsoluteItems.Count-1 do
|
|
|
+ TObject(FAbsoluteItems[i]).Free;
|
|
|
+ FAbsoluteItems.Clear;
|
|
|
+end;
|
|
|
+
|
|
|
procedure TFLLineLayouter.ClearLineItems;
|
|
|
var
|
|
|
i: Integer;
|
|
@@ -1736,14 +1773,16 @@ begin
|
|
|
FLineItems.Clear;
|
|
|
end;
|
|
|
|
|
|
-function TFLLineLayouter.AddLineItem(ChildNode: TUsedLayoutNode; NodeClass: TLineItemClass
|
|
|
+function TFLLineLayouter.AddAbsoluteItem(ChildNode: TUsedLayoutNode; NodeClass: TLineItemClass
|
|
|
): TLineItem;
|
|
|
begin
|
|
|
Result:=NodeClass.Create;
|
|
|
- if FLineItems=nil then
|
|
|
- FLineItems:=TFPList.Create;
|
|
|
- FLineItems.Add(Result);
|
|
|
+ if FAbsoluteItems=nil then
|
|
|
+ FAbsoluteItems:=TFPList.Create;
|
|
|
+ FAbsoluteItems.Add(Result);
|
|
|
Result.Node:=ChildNode;
|
|
|
+ Result.StaticLeft:=NaN;
|
|
|
+ Result.StaticTop:=NaN;
|
|
|
end;
|
|
|
|
|
|
procedure TFLLineLayouter.ComputeChildAttributes(Item: TLineItem;
|
|
@@ -1755,6 +1794,8 @@ end;
|
|
|
|
|
|
destructor TFLLineLayouter.Destroy;
|
|
|
begin
|
|
|
+ ClearAbsoluteItems;
|
|
|
+ FreeAndNil(FAbsoluteItems);
|
|
|
ClearLineItems;
|
|
|
FreeAndNil(FLineItems);
|
|
|
inherited Destroy;
|