|
@@ -37,7 +37,7 @@ type
|
|
|
Mode: TFresnelLayoutMode;
|
|
|
WithScroll: boolean;
|
|
|
MaxWidth, MaxHeight: TFresnelLength;
|
|
|
- ContentSize: TFresnelLayoutNode.TContentSize;
|
|
|
+ ContentSize: TFreIntrinsicContentSize;
|
|
|
end;
|
|
|
TLayoutSizeArray = array of TLayoutSize;
|
|
|
var
|
|
@@ -49,13 +49,13 @@ type
|
|
|
procedure DeductUsedLengths(NoChildren: boolean); virtual;
|
|
|
procedure ClearCachedLayoutSizes; virtual;
|
|
|
function GetCachedLayoutSize(aMode: TFresnelLayoutMode; aMaxWidth, aMaxHeight: TFresnelLength;
|
|
|
- aWithScroll: boolean; out aSize: TFresnelLayoutNode.TContentSize): boolean; virtual;
|
|
|
+ aWithScroll: boolean; out aSize: TFreIntrinsicContentSize): boolean; virtual;
|
|
|
procedure AddCachedLayoutSize(aMode: TFresnelLayoutMode; aMaxWidth, aMaxHeight: TFresnelLength;
|
|
|
- aWithScroll: boolean; const aSize: TFresnelLayoutNode.TContentSize); virtual;
|
|
|
+ aWithScroll: boolean; const aSize: TFreIntrinsicContentSize); virtual;
|
|
|
function ComputeLayoutContent(aMode: TFresnelLayoutMode; aMaxWidth, aMaxHeight: TFresnelLength;
|
|
|
- Commit: boolean): TFresnelPoint; virtual; abstract;
|
|
|
+ Commit: boolean): TFreIntrinsicContentSize; virtual; abstract;
|
|
|
function GetIntrinsicContentSize(aMode: TFresnelLayoutMode; aMaxWidth: TFresnelLength=NaN;
|
|
|
- aMaxHeight: TFresnelLength=NaN; aWithScroll: boolean = true): TFresnelLayoutNode.TContentSize; virtual;
|
|
|
+ aMaxHeight: TFresnelLength=NaN; aWithScroll: boolean = true): TFreIntrinsicContentSize; virtual;
|
|
|
function GetViewport: TFresnelViewport;
|
|
|
end;
|
|
|
TFLNodeLayouterClass = class of TFLNodeLayouter;
|
|
@@ -72,10 +72,10 @@ type
|
|
|
procedure ComputeScrollbarsNoChildren; virtual;
|
|
|
procedure GetScrollGutterWidths(Horizontal: boolean; out LT, RB: TFresnelLength);
|
|
|
procedure AddScrollGutter(Horizontal: boolean);
|
|
|
- procedure ApplyScrollSize(const aSize: TContentSize);
|
|
|
+ procedure ApplyScrollSize(const aSize: TFreIntrinsicContentSize);
|
|
|
procedure DeductUsedLengths(NoChildren: boolean); virtual;
|
|
|
function GetIntrinsicContentSize(aMode: TFresnelLayoutMode; aMaxWidth: TFresnelLength=NaN;
|
|
|
- aMaxHeight: TFresnelLength=NaN): TContentSize; override;
|
|
|
+ aMaxHeight: TFresnelLength=NaN): TFreIntrinsicContentSize; override;
|
|
|
destructor Destroy; override;
|
|
|
end;
|
|
|
|
|
@@ -95,6 +95,8 @@ type
|
|
|
StaticTop: TFresnelLength;
|
|
|
ContentBoxWidth: TFresnelLength;
|
|
|
ContentBoxHeight: TFresnelLength;
|
|
|
+ IntrinsicWidth: TFresnelLength;
|
|
|
+ IntrinsicHeight: TFresnelLength;
|
|
|
end;
|
|
|
TLineItemClass = class of TLineItem;
|
|
|
|
|
@@ -104,7 +106,7 @@ type
|
|
|
procedure PlaceLineItems; virtual;
|
|
|
function PlaceAbsoluteItem(ChildNode: TUsedLayoutNode; aMode: TFresnelLayoutMode;
|
|
|
aMaxWidth, aMaxHeight: TFresnelLength; const DefaultPos: TFresnelPoint;
|
|
|
- Commit: boolean): TFresnelPoint; virtual;
|
|
|
+ Commit: boolean): TFreIntrinsicContentSize; virtual;
|
|
|
function AddAbsoluteItem(ChildNode: TUsedLayoutNode; NodeClass: TLineItemClass): TLineItem; virtual;
|
|
|
function AddLineItem(ChildNode: TUsedLayoutNode; NodeClass: TLineItemClass): TLineItem; virtual;
|
|
|
procedure ClearAbsoluteItems; virtual;
|
|
@@ -145,7 +147,9 @@ type
|
|
|
procedure PlaceLineItems; override;
|
|
|
public
|
|
|
procedure DeductUsedLengths(NoChildren: boolean); override;
|
|
|
- function ComputeLayoutContent(aMode: TFresnelLayoutMode; aMaxWidth, aMaxHeight: TFresnelLength; Commit: boolean): TFresnelPoint; override;
|
|
|
+ function ComputeLayoutContent(aMode: TFresnelLayoutMode; aMaxWidth, aMaxHeight: TFresnelLength; Commit:
|
|
|
+ boolean): TFreIntrinsicContentSize; override;
|
|
|
+ function MergeMargins(a, b: TFresnelLength): TFresnelLength;
|
|
|
end;
|
|
|
|
|
|
{ TFLFlexLayouter }
|
|
@@ -179,24 +183,26 @@ type
|
|
|
MainIsReverse: boolean; // flex-direction is row-reverse or column-reverse
|
|
|
procedure StartLine; virtual;
|
|
|
procedure EndLine(MaxMainSize, MainGap: TFresnelLength;
|
|
|
- Commit: boolean; var NewContentSize: TFresnelPoint); virtual;
|
|
|
+ Commit: boolean; var NewContentSize: TFreIntrinsicContentSize); virtual;
|
|
|
procedure FlexLineMainDirection(MaxMainSize, MainGap: TFresnelLength; Commit: boolean;
|
|
|
- var NewContentSize: TFresnelPoint); virtual;
|
|
|
+ var NewContentSize: TFreIntrinsicContentSize); virtual;
|
|
|
procedure FlexLineCrossDirection(Commit: boolean;
|
|
|
- var NewContentSize: TFresnelPoint); virtual;
|
|
|
+ var NewContentSize: TFreIntrinsicContentSize); virtual;
|
|
|
procedure PlaceLineItems; override;
|
|
|
procedure ComputeChildAttributes(Item: TLineItem; El: TFresnelElement); override;
|
|
|
public
|
|
|
procedure Init; override;
|
|
|
function GetComputedGap(IsHorizontal: boolean): TFresnelLength;
|
|
|
- function ComputeLayoutContent(aMode: TFresnelLayoutMode; aMaxWidth, aMaxHeight: TFresnelLength; Commit: boolean): TFresnelPoint; override;
|
|
|
+ function ComputeLayoutContent(aMode: TFresnelLayoutMode; aMaxWidth, aMaxHeight: TFresnelLength;
|
|
|
+ Commit: boolean): TFreIntrinsicContentSize; override;
|
|
|
end;
|
|
|
|
|
|
{ TFLGridLayouter }
|
|
|
|
|
|
TFLGridLayouter = class(TFLNodeLayouter)
|
|
|
public
|
|
|
- function ComputeLayoutContent(aMode: TFresnelLayoutMode; aMaxWidth, aMaxHeight: TFresnelLength; Commit: boolean): TFresnelPoint; override;
|
|
|
+ function ComputeLayoutContent(aMode: TFresnelLayoutMode; aMaxWidth, aMaxHeight: TFresnelLength;
|
|
|
+ Commit: boolean): TFreIntrinsicContentSize; override;
|
|
|
end;
|
|
|
|
|
|
{ TViewportLayouter }
|
|
@@ -254,8 +260,7 @@ end;
|
|
|
procedure TFLNodeLayouter.Apply;
|
|
|
var
|
|
|
MaxWidth, MaxHeight, aClientWidth, aClientHeight: TFresnelLength;
|
|
|
- ContSize: TFresnelLayoutNode.TContentSize;
|
|
|
- Size: TFresnelPoint;
|
|
|
+ Size: TFreIntrinsicContentSize;
|
|
|
HasMaxWidth, HasMaxHeight: Boolean;
|
|
|
El: TFresnelElement;
|
|
|
aClientBox: TFresnelRect;
|
|
@@ -280,10 +285,10 @@ begin
|
|
|
{$IFDEF VerboseFresnelScrolling}
|
|
|
writeln('TFLNodeLayouter.Apply "',Node.Element.Name,'" Before Intrinsic: CanScrollX=',Node.CanScrollX,' CanScrollY=',Node.CanScrollY,' MaxSize=',FloatToCSSStr(MaxWidth),'x',FloatToCSSStr(MaxHeight),' GutterHorz=',Node.GutterHorizontal,' GutterVert=',Node.GutterVertical);
|
|
|
{$ENDIF}
|
|
|
- ContSize:=GetIntrinsicContentSize(flmMax,MaxWidth,MaxHeight);
|
|
|
- Node.ApplyScrollSize(ContSize);
|
|
|
+ Size:=GetIntrinsicContentSize(flmMax,MaxWidth,MaxHeight);
|
|
|
+ Node.ApplyScrollSize(Size);
|
|
|
{$IFDEF VerboseFresnelScrolling}
|
|
|
- writeln('TFLNodeLayouter.Apply "',Node.Element.Name,'" IntrinsicContentSize: Size=',FloatToCSSStr(ContSize.Width),'x',FloatToCSSStr(ContSize.Height),' ScrollSize=',FloatToCSSStr(ContSize.ScrollWidth),'x',FloatToCSSStr(ContSize.ScrollHeight),' NeedGutterHorz=',ContSize.NeedGutterHorizontal,' Vert=',ContSize.NeedGutterVertical,' Gutter:L=',FloatToCSSStr(Node.ScrollGutterLeft),',R=',FloatToCSSStr(Node.ScrollGutterRight),',T=',FloatToCSSStr(Node.ScrollGutterTop),',B=',FloatToCSSStr(Node.ScrollGutterBottom));
|
|
|
+ writeln('TFLNodeLayouter.Apply "',Node.Element.Name,'" IntrinsicContentSize: Size=',FloatToCSSStr(Size.Width),'x',FloatToCSSStr(Size.Height),' ScrollSize=',FloatToCSSStr(Size.ScrollWidth),'x',FloatToCSSStr(Size.ScrollHeight),' NeedGutterHorz=',Size.NeedGutterHorizontal,' Vert=',Size.NeedGutterVertical,' Gutter:L=',FloatToCSSStr(Node.ScrollGutterLeft),',R=',FloatToCSSStr(Node.ScrollGutterRight),',T=',FloatToCSSStr(Node.ScrollGutterTop),',B=',FloatToCSSStr(Node.ScrollGutterBottom));
|
|
|
{$ENDIF}
|
|
|
end;
|
|
|
|
|
@@ -306,22 +311,22 @@ begin
|
|
|
{$ENDIF}
|
|
|
Size:=ComputeLayoutContent(flmMax,aClientWidth,aClientHeight,true);
|
|
|
{$IFDEF VerboseFresnelScrolling}
|
|
|
- writeln('TFLNodeLayouter.Apply "',Node.Element.Name,'" ContentSize: ',FloatToCSSStr(Size.X),'x',FloatToCSSStr(Size.Y));
|
|
|
+ writeln('TFLNodeLayouter.Apply "',Node.Element.Name,'" Size: ',FloatToCSSStr(Size.Width),'x',FloatToCSSStr(Size.Height),' Scroll: ',FloatToCSSStr(Size.ScrollWidth),'x',FloatToCSSStr(Size.ScrollWidth));
|
|
|
{$ENDIF}
|
|
|
if IsNan(Node.Width) then
|
|
|
begin
|
|
|
- Node.Width:=Size.X;
|
|
|
+ Node.Width:=Size.Width;
|
|
|
if Node.Width>aClientWidth then
|
|
|
Node.Width:=aClientWidth;
|
|
|
end;
|
|
|
if IsNan(Node.Height) then
|
|
|
begin
|
|
|
- Node.Height:=Node.FitHeight(Size.Y);
|
|
|
+ Node.Height:=Node.FitHeight(Size.Height);
|
|
|
if Node.Height>aClientHeight then
|
|
|
Node.Height:=aClientHeight;
|
|
|
end;
|
|
|
- Node.ScrollWidth:=Max(Size.X,aClientWidth);
|
|
|
- Node.ScrollHeight:=Max(Size.Y,aClientHeight);
|
|
|
+ Node.ScrollWidth:=Max(Size.ScrollWidth,aClientWidth);
|
|
|
+ Node.ScrollHeight:=Max(Size.ScrollHeight,aClientHeight);
|
|
|
{$IFDEF VerboseFresnelScrolling}
|
|
|
writeln('TFLNodeLayouter.Apply "',Node.Element.Name,'" ScrollSize: ',FloatToCSSStr(Node.ScrollWidth),'x',FloatToCSSStr(Node.ScrollHeight),' Width=',FloatToCSSStr(Node.Width),' Height=',FloatToCSSStr(Node.Height));
|
|
|
{$ENDIF}
|
|
@@ -343,11 +348,11 @@ begin
|
|
|
//writeln('TFLNodeLayouter.Apply "',Node.Element.Name,'" no scroll MaxWidth=',FloatToCSSStr(MaxWidth),' MaxHeight=',FloatToCSSStr(MaxHeight));
|
|
|
Size:=ComputeLayoutContent(flmMax,MaxWidth,MaxHeight,true);
|
|
|
if IsNan(Node.Width) then
|
|
|
- Node.Width:=Node.FitWidth(Size.X);
|
|
|
+ Node.Width:=Node.FitWidth(Size.Width);
|
|
|
if IsNan(Node.Height) then
|
|
|
- Node.Height:=Node.FitHeight(Size.Y);
|
|
|
- Node.ScrollWidth:=Max(Size.X,Node.Width);
|
|
|
- Node.ScrollHeight:=Max(Size.Y,Node.Height);
|
|
|
+ Node.Height:=Node.FitHeight(Size.Height);
|
|
|
+ Node.ScrollWidth:=Max(Size.ScrollWidth,Node.Width);
|
|
|
+ Node.ScrollHeight:=Max(Size.ScrollHeight,Node.Height);
|
|
|
end;
|
|
|
|
|
|
// clipping
|
|
@@ -376,7 +381,7 @@ begin
|
|
|
end;
|
|
|
|
|
|
function TFLNodeLayouter.GetCachedLayoutSize(aMode: TFresnelLayoutMode; aMaxWidth,
|
|
|
- aMaxHeight: TFresnelLength; aWithScroll: boolean; out aSize: TFresnelLayoutNode.TContentSize
|
|
|
+ aMaxHeight: TFresnelLength; aWithScroll: boolean; out aSize: TFreIntrinsicContentSize
|
|
|
): boolean;
|
|
|
|
|
|
function CheckMax(OldMax, NewMax, OldResult: TFresnelLength): boolean;
|
|
@@ -453,12 +458,12 @@ begin
|
|
|
aSize:=ContentSize;
|
|
|
exit(true);
|
|
|
end;
|
|
|
- aSize:=Default(TFresnelLayoutNode.TContentSize);
|
|
|
+ aSize:=Default(TFreIntrinsicContentSize);
|
|
|
Result:=false;
|
|
|
end;
|
|
|
|
|
|
procedure TFLNodeLayouter.AddCachedLayoutSize(aMode: TFresnelLayoutMode; aMaxWidth,
|
|
|
- aMaxHeight: TFresnelLength; aWithScroll: boolean; const aSize: TFresnelLayoutNode.TContentSize);
|
|
|
+ aMaxHeight: TFresnelLength; aWithScroll: boolean; const aSize: TFreIntrinsicContentSize);
|
|
|
var
|
|
|
l: integer;
|
|
|
begin
|
|
@@ -474,24 +479,18 @@ begin
|
|
|
end;
|
|
|
|
|
|
function TFLNodeLayouter.GetIntrinsicContentSize(aMode: TFresnelLayoutMode;
|
|
|
- aMaxWidth: TFresnelLength; aMaxHeight: TFresnelLength; aWithScroll: boolean): TFresnelLayoutNode.
|
|
|
- TContentSize;
|
|
|
+ aMaxWidth: TFresnelLength; aMaxHeight: TFresnelLength; aWithScroll: boolean):
|
|
|
+ TFreIntrinsicContentSize;
|
|
|
var
|
|
|
GutterLeft, GutterRight, GutterTop, GutterBottom: TFresnelLength;
|
|
|
|
|
|
procedure Compute(CurMode: TFresnelLayoutMode; CurMaxWidth, CurMaxHeight: TFresnelLength;
|
|
|
AddGutter: boolean);
|
|
|
- var
|
|
|
- aSize: TFresnelPoint;
|
|
|
begin
|
|
|
if not GetCachedLayoutSize(CurMode,CurMaxWidth,CurMaxHeight,false,Result) then
|
|
|
begin
|
|
|
- aSize:=ComputeLayoutContent(CurMode,CurMaxWidth,CurMaxHeight,false);
|
|
|
- Result:=Default(TFresnelLayoutNode.TContentSize);
|
|
|
- Result.Width:=aSize.X;
|
|
|
- Result.Height:=aSize.Y;
|
|
|
- Result.ScrollWidth:=aSize.X;
|
|
|
- Result.ScrollHeight:=aSize.Y;
|
|
|
+ Result:=ComputeLayoutContent(CurMode,CurMaxWidth,CurMaxHeight,false);
|
|
|
+ Result:=Default(TFreIntrinsicContentSize);
|
|
|
AddCachedLayoutSize(CurMode,CurMaxWidth,CurMaxHeight,false,Result);
|
|
|
end;
|
|
|
if AddGutter then begin
|
|
@@ -618,12 +617,7 @@ begin
|
|
|
|
|
|
if not Done then
|
|
|
begin
|
|
|
- aSize:=ComputeLayoutContent(aMode,aMaxWidth,aMaxHeight,false);
|
|
|
- Result:=Default(TFresnelLayoutNode.TContentSize);
|
|
|
- Result.Width:=aSize.X;
|
|
|
- Result.Height:=aSize.Y;
|
|
|
- Result.ScrollWidth:=aSize.X;
|
|
|
- Result.ScrollHeight:=aSize.Y;
|
|
|
+ Result:=ComputeLayoutContent(aMode,aMaxWidth,aMaxHeight,false);
|
|
|
end;
|
|
|
AddCachedLayoutSize(aMode,aMaxWidth,aMaxHeight,aWithScroll,Result);
|
|
|
end;
|
|
@@ -871,7 +865,7 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-procedure TUsedLayoutNode.ApplyScrollSize(const aSize: TContentSize);
|
|
|
+procedure TUsedLayoutNode.ApplyScrollSize(const aSize: TFreIntrinsicContentSize);
|
|
|
begin
|
|
|
ScrollWidth:=aSize.ScrollWidth;
|
|
|
ScrollHeight:=aSize.ScrollHeight;
|
|
@@ -986,12 +980,12 @@ begin
|
|
|
end;
|
|
|
|
|
|
function TUsedLayoutNode.GetIntrinsicContentSize(aMode: TFresnelLayoutMode;
|
|
|
- aMaxWidth: TFresnelLength; aMaxHeight: TFresnelLength): TContentSize;
|
|
|
+ aMaxWidth: TFresnelLength; aMaxHeight: TFresnelLength): TFreIntrinsicContentSize;
|
|
|
begin
|
|
|
if Layouter<>nil then
|
|
|
Result:=Layouter.GetIntrinsicContentSize(aMode,aMaxWidth,aMaxHeight)
|
|
|
else
|
|
|
- Result:=Default(TContentSize);
|
|
|
+ Result:=Default(TFreIntrinsicContentSize);
|
|
|
end;
|
|
|
|
|
|
destructor TUsedLayoutNode.Destroy;
|
|
@@ -1118,36 +1112,50 @@ begin
|
|
|
end;
|
|
|
|
|
|
function TFLFlowLayouter.ComputeLayoutContent(aMode: TFresnelLayoutMode; aMaxWidth,
|
|
|
- aMaxHeight: TFresnelLength; Commit: boolean): TFresnelPoint;
|
|
|
+ aMaxHeight: TFresnelLength; Commit: boolean): TFreIntrinsicContentSize;
|
|
|
var
|
|
|
ChildIndex: Integer;
|
|
|
ChildNode: TUsedLayoutNode;
|
|
|
ChildEl, El: TFresnelElement;
|
|
|
IsInline: Boolean;
|
|
|
NewChildRight, CurSpace, OldMarginBoxBottom,
|
|
|
- ChildMBoxLeft, ChildMBoxRight { MarginBox relative to parent ContentBox left },
|
|
|
+ ChildMBoxLeft, ChildMBoxRight { MarginBox relative to parent ClientBox left },
|
|
|
ChildWidth, ChildHeight { ContentBox },
|
|
|
ChildMinWidth, ChildMinHeight { ContentBox, at least 0 },
|
|
|
ChildMaxWidth, ChildMaxHeight { ContentBox, can be NaN },
|
|
|
ChildMarginLeft, ChildMarginRight, ChildMarginTop, ChildMarginBottom,
|
|
|
ChildPadBorderX, ChildPadBorderY: TFresnelLength;
|
|
|
- ChildPrefSize, ChildDefPos: TFresnelPoint;
|
|
|
+ ChildPrefSize: TFreIntrinsicContentSize;
|
|
|
+ ChildDefPos: TFresnelPoint;
|
|
|
AbsItem: TLineItem;
|
|
|
|
|
|
procedure AddLineNodeCache;
|
|
|
var
|
|
|
N: TFlowItem;
|
|
|
+ r: TFresnelLength;
|
|
|
begin
|
|
|
FLLog(etDebug,['AddLineNodeCache ',ChildEl.GetPath,' L=',FloatToStr(ChildMBoxLeft),',R=',FloatToStr(ChildMBoxRight),',W=',FloatToStr(ChildWidth),',H=',FloatToStr(ChildHeight)]);
|
|
|
N:=TFlowItem(AddLineItem(ChildNode,TFlowItem));
|
|
|
N.StaticLeft:=ChildMBoxLeft;
|
|
|
N.ContentBoxWidth:=ChildWidth;
|
|
|
N.ContentBoxHeight:=ChildHeight;
|
|
|
- Result.X:=Max(Result.X,ChildMBoxRight);
|
|
|
+ N.IntrinsicWidth:=Max(ChildWidth,ChildPrefSize.ScrollWidth);
|
|
|
+ N.IntrinsicHeight:=Max(ChildHeight,ChildPrefSize.ScrollHeight);
|
|
|
+ Result.Width:=Max(Result.Width,ChildMBoxRight);
|
|
|
+
|
|
|
+ if Result.ScrollWidth<Result.Width then
|
|
|
+ Result.ScrollWidth:=Result.Width;
|
|
|
+ r:=ChildPrefSize.ScrollWidth-ChildWidth;
|
|
|
+ if r>0 then
|
|
|
+ begin
|
|
|
+ r:=ChildMBoxRight+r;
|
|
|
+ if Result.ScrollWidth<r then
|
|
|
+ Result.ScrollWidth:=r;
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
begin
|
|
|
- Result:=default(TFresnelPoint);
|
|
|
+ Result:=default(TFreIntrinsicContentSize);
|
|
|
|
|
|
//writeln('TFLFlowLayouter.ComputeLayoutContent ',Node.Element.GetPath,' ',aMode,' MaxWidth=',FloatToCSSStr(aMaxWidth),' MaxHeight=',FloatToCSSStr(aMaxHeight),' Commit=',Commit);
|
|
|
|
|
@@ -1223,7 +1231,9 @@ begin
|
|
|
else if IsNan(aMaxWidth) then
|
|
|
CurSpace:=NaN
|
|
|
else
|
|
|
- CurSpace:=Max(0,aMaxWidth-FLineBorderBoxRight-Max(FLineMarginRight,ChildNode.MarginLeft)-ChildNode.MarginRight);
|
|
|
+ CurSpace:=Max(0,aMaxWidth-FLineBorderBoxRight
|
|
|
+ -MergeMargins(FLineMarginRight,ChildNode.MarginLeft)
|
|
|
+ -ChildNode.MarginRight);
|
|
|
|
|
|
//writeln('TFLFlowLayouter.ComputeLayoutContent ',ChildEl.GetPath,' Margin=',FloatToStr(ChildMarginLeft),',',FloatToStr(ChildMarginTop),',',FloatToStr(ChildMarginRight),',',FloatToStr(ChildMarginBottom),' Border=',FloatToStr(ChildBorderLeft),',',FloatToStr(ChildBorderTop),',',FloatToStr(ChildBorderRight),',',FloatToStr(ChildBorderBottom),' Padding=',FloatToStr(ChildPaddingLeft),',',FloatToStr(ChildPaddingTop),',',FloatToStr(ChildPaddingRight),',',FloatToStr(ChildPaddingBottom));
|
|
|
|
|
@@ -1248,53 +1258,50 @@ begin
|
|
|
//writeln('TFLFlowLayouter.ComputeLayoutContent BLOCK FULL LINE: ',ChildEl.GetPath,' CurSpace=',FloatToStr(CurSpace),' ChildPadBorderX=',FloatToStr(ChildPadBorderX));
|
|
|
ChildWidth:=CurSpace-ChildPadBorderX;
|
|
|
end;
|
|
|
- if not IsNan(ChildWidth) then
|
|
|
+ if IsNan(ChildWidth) then
|
|
|
begin
|
|
|
+ if not IsNan(CurSpace) then
|
|
|
+ begin
|
|
|
+ if not IsNan(ChildMaxWidth) then
|
|
|
+ CurSpace:=Min(CurSpace-ChildPadBorderX,ChildMaxWidth);
|
|
|
+ CurSpace:=Max(CurSpace-ChildPadBorderX,ChildMinWidth);
|
|
|
+ end;
|
|
|
+ end else begin
|
|
|
if not IsNan(ChildMaxWidth) then
|
|
|
ChildWidth:=Min(ChildWidth,ChildMaxWidth);
|
|
|
ChildWidth:=Max(ChildWidth,ChildMinWidth);
|
|
|
+ CurSpace:=ChildWidth;
|
|
|
end;
|
|
|
|
|
|
- if IsNan(ChildWidth) or IsNan(ChildHeight) then
|
|
|
+ if (aMode=flmMax) or IsNan(ChildWidth) or IsNan(ChildHeight) then
|
|
|
begin
|
|
|
- // one or both sides are dynamic
|
|
|
- if IsNan(ChildWidth) then
|
|
|
- begin
|
|
|
- if not IsNan(CurSpace) then
|
|
|
- begin
|
|
|
- if not IsNan(ChildMaxWidth) then
|
|
|
- CurSpace:=Min(CurSpace-ChildPadBorderX,ChildMaxWidth);
|
|
|
- CurSpace:=Max(CurSpace-ChildPadBorderX,ChildMinWidth);
|
|
|
- end;
|
|
|
- end else begin
|
|
|
- CurSpace:=ChildWidth;
|
|
|
- end;
|
|
|
ChildPrefSize:=ChildEl.GetIntrinsicContentSize(aMode,CurSpace,NaN);
|
|
|
//if ChildEl.Name='CaptionLabel' then
|
|
|
- // writeln('TFLFlowLayouter.ComputeLayoutContent ',ChildEl.GetPath,' MaxWidth=',CurSpace,' Preferred=',ChildPrefSize.ToString,' ChildPadBorderX=',ChildPadBorderX,' ChildPadBorderY=',ChildPadBorderY);
|
|
|
+ writeln('TFLFlowLayouter.ComputeLayoutContent ',ChildEl.GetPath,' MaxWidth=',FloatToCSSStr(CurSpace),' Preferred=',ChildPrefSize.ToString,' ChildPadBorderX=',FloatToCSSStr(ChildPadBorderX),' ChildPadBorderY=',FloatToCSSStr(ChildPadBorderY));
|
|
|
// apply min, max
|
|
|
if IsNan(ChildWidth) then
|
|
|
begin
|
|
|
- ChildWidth:=ChildPrefSize.X;
|
|
|
+ ChildWidth:=ChildPrefSize.Width;
|
|
|
if not IsNan(ChildMaxWidth) then
|
|
|
ChildWidth:=Min(ChildWidth,ChildMaxWidth);
|
|
|
ChildWidth:=Max(ChildWidth,ChildMinWidth);
|
|
|
end;
|
|
|
if IsNan(ChildHeight) then
|
|
|
begin
|
|
|
- ChildHeight:=ChildPrefSize.Y;
|
|
|
+ ChildHeight:=ChildPrefSize.Height;
|
|
|
if not IsNan(ChildMaxHeight) then
|
|
|
ChildHeight:=Min(ChildHeight,ChildMaxHeight);
|
|
|
ChildHeight:=Max(ChildHeight,ChildMinHeight);
|
|
|
end;
|
|
|
- end;
|
|
|
+ end else
|
|
|
+ ChildPrefSize:=Default(TFreIntrinsicContentSize);
|
|
|
|
|
|
NewChildRight:=0;
|
|
|
if (FLineItems.Count>0) and IsInline and (not IsNan(aMaxWidth)) then
|
|
|
begin
|
|
|
// check if inline element fits in line
|
|
|
NewChildRight:=FLineBorderBoxRight
|
|
|
- +Max(FLineMarginRight,ChildMarginLeft) // margin collapsing
|
|
|
+ +MergeMargins(FLineMarginRight,ChildMarginLeft)
|
|
|
+ChildWidth+ChildPadBorderX
|
|
|
+ChildMarginRight;
|
|
|
if NewChildRight>aMaxWidth then
|
|
@@ -1368,7 +1375,7 @@ begin
|
|
|
end;
|
|
|
EndLine(Commit);
|
|
|
|
|
|
- if Commit and (FAbsoluteItems<>nil) then
|
|
|
+ if (FAbsoluteItems<>nil) and (Commit or (aMode=flmMax)) then
|
|
|
begin
|
|
|
// place absolute items
|
|
|
for ChildIndex:=0 to FAbsoluteItems.Count-1 do
|
|
@@ -1379,20 +1386,46 @@ begin
|
|
|
ChildDefPos.X:=AbsItem.StaticLeft;
|
|
|
ChildDefPos.Y:=AbsItem.StaticTop;
|
|
|
|
|
|
- PlaceAbsoluteItem(ChildNode,aMode,aMaxWidth,aMaxHeight,ChildDefPos,Commit);
|
|
|
+ ChildPrefSize:=PlaceAbsoluteItem(ChildNode,aMode,aMaxWidth,aMaxHeight,ChildDefPos,Commit);
|
|
|
+ if Result.ScrollWidth<ChildPrefSize.ScrollWidth then
|
|
|
+ Result.ScrollWidth:=ChildPrefSize.ScrollWidth;
|
|
|
+ if Result.ScrollHeight<ChildPrefSize.ScrollHeight then
|
|
|
+ Result.ScrollHeight:=ChildPrefSize.ScrollHeight;
|
|
|
end;
|
|
|
- ClearAbsoluteItems;
|
|
|
end;
|
|
|
+ if FAbsoluteItems<>nil then
|
|
|
+ ClearAbsoluteItems;
|
|
|
|
|
|
- Result.Y:=Max(Result.Y,FLastLineBorderBoxBottom+FLastLineMarginBottom);
|
|
|
+ Result.Height:=Max(Result.Height,FLastLineBorderBoxBottom+FLastLineMarginBottom);
|
|
|
+end;
|
|
|
+
|
|
|
+function TFLFlowLayouter.MergeMargins(a, b: TFresnelLength): TFresnelLength;
|
|
|
+begin
|
|
|
+ if a>=0 then
|
|
|
+ begin
|
|
|
+ if b>=a then
|
|
|
+ Result:=b // 0<=a<=b -> maximum b
|
|
|
+ else if b>=0 then
|
|
|
+ Result:=a // 0<=b<a -> maximum a
|
|
|
+ else
|
|
|
+ Result:=a+b; // a>=0, b<0 -> sum
|
|
|
+ end else begin
|
|
|
+ // a<0
|
|
|
+ if b>=0 then
|
|
|
+ Result:=a+b // a<0, b>=0 -> sum
|
|
|
+ else if b<a then
|
|
|
+ Result:=b // b<a<0
|
|
|
+ else
|
|
|
+ Result:=a; // a<=b<=0 -> minimum a
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
{ TFLGridLayouter }
|
|
|
|
|
|
function TFLGridLayouter.ComputeLayoutContent(aMode: TFresnelLayoutMode; aMaxWidth,
|
|
|
- aMaxHeight: TFresnelLength; Commit: boolean): TFresnelPoint;
|
|
|
+ aMaxHeight: TFresnelLength; Commit: boolean): TFreIntrinsicContentSize;
|
|
|
begin
|
|
|
- Result:=Default(TFresnelPoint);
|
|
|
+ Result:=Default(TFreIntrinsicContentSize);
|
|
|
|
|
|
if Commit then ;
|
|
|
if aMode=flmMax then ;
|
|
@@ -1408,7 +1441,7 @@ begin
|
|
|
end;
|
|
|
|
|
|
procedure TFLFlexLayouter.EndLine(MaxMainSize, MainGap: TFresnelLength; Commit: boolean;
|
|
|
- var NewContentSize: TFresnelPoint);
|
|
|
+ var NewContentSize: TFreIntrinsicContentSize);
|
|
|
begin
|
|
|
if FLineItems.Count=0 then exit;
|
|
|
FlexLineMainDirection(MaxMainSize,MainGap,Commit,NewContentSize);
|
|
@@ -1419,7 +1452,7 @@ begin
|
|
|
end;
|
|
|
|
|
|
procedure TFLFlexLayouter.FlexLineMainDirection(MaxMainSize, MainGap: TFresnelLength;
|
|
|
- Commit: boolean; var NewContentSize: TFresnelPoint);
|
|
|
+ Commit: boolean; var NewContentSize: TFreIntrinsicContentSize);
|
|
|
const
|
|
|
MinAdjust = 0.0001;
|
|
|
var
|
|
@@ -1460,9 +1493,9 @@ var
|
|
|
procedure AdjustMainContentSize(p: TFresnelLength);
|
|
|
begin
|
|
|
if MainIsRow then
|
|
|
- NewContentSize.X:=Max(NewContentSize.X,p)
|
|
|
+ NewContentSize.Width:=Max(NewContentSize.Width,p)
|
|
|
else
|
|
|
- NewContentSize.Y:=Max(NewContentSize.Y,p);
|
|
|
+ NewContentSize.Height:=Max(NewContentSize.Height,p);
|
|
|
end;
|
|
|
|
|
|
var
|
|
@@ -1643,8 +1676,8 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-procedure TFLFlexLayouter.FlexLineCrossDirection(Commit: boolean; var NewContentSize: TFresnelPoint
|
|
|
- );
|
|
|
+procedure TFLFlexLayouter.FlexLineCrossDirection(Commit: boolean;
|
|
|
+ var NewContentSize: TFreIntrinsicContentSize);
|
|
|
var
|
|
|
i: Integer;
|
|
|
Item: TFlexItem;
|
|
@@ -1717,9 +1750,9 @@ begin
|
|
|
end;
|
|
|
|
|
|
if MainIsRow then
|
|
|
- NewContentSize.Y:=Max(NewContentSize.Y,MaxSize)
|
|
|
+ NewContentSize.Height:=Max(NewContentSize.Height,MaxSize)
|
|
|
else
|
|
|
- NewContentSize.X:=Max(NewContentSize.X,MaxSize);
|
|
|
+ NewContentSize.Width:=Max(NewContentSize.Width,MaxSize);
|
|
|
end;
|
|
|
|
|
|
procedure TFLFlexLayouter.PlaceLineItems;
|
|
@@ -1732,7 +1765,7 @@ procedure TFLFlexLayouter.ComputeChildAttributes(Item: TLineItem;
|
|
|
var
|
|
|
FlexItem: TFlexItem;
|
|
|
ItemNode: TUsedLayoutNode;
|
|
|
- Size: TFresnelLayoutNode.TContentSize;
|
|
|
+ Size: TFreIntrinsicContentSize;
|
|
|
begin
|
|
|
inherited ComputeChildAttributes(Item, El);
|
|
|
|
|
@@ -1829,7 +1862,7 @@ begin
|
|
|
end;
|
|
|
|
|
|
function TFLFlexLayouter.ComputeLayoutContent(aMode: TFresnelLayoutMode; aMaxWidth,
|
|
|
- aMaxHeight: TFresnelLength; Commit: boolean): TFresnelPoint;
|
|
|
+ aMaxHeight: TFresnelLength; Commit: boolean): TFreIntrinsicContentSize;
|
|
|
var
|
|
|
ChildIndex: Integer;
|
|
|
ChildNode: TUsedLayoutNode;
|
|
@@ -1841,7 +1874,7 @@ var
|
|
|
ChildDefPos: TFresnelPoint;
|
|
|
ItemAdded: Boolean;
|
|
|
begin
|
|
|
- Result:=default(TFresnelPoint);
|
|
|
+ Result:=default(TFreIntrinsicContentSize);
|
|
|
|
|
|
if MainIsRow then
|
|
|
begin
|
|
@@ -1990,19 +2023,18 @@ end;
|
|
|
|
|
|
function TFLLineLayouter.PlaceAbsoluteItem(ChildNode: TUsedLayoutNode; aMode: TFresnelLayoutMode;
|
|
|
aMaxWidth, aMaxHeight: TFresnelLength; const DefaultPos: TFresnelPoint; Commit: boolean
|
|
|
- ): TFresnelPoint;
|
|
|
+ ): TFreIntrinsicContentSize;
|
|
|
// returns right, bottom marginbox, so the parent can compute its needed content size
|
|
|
var
|
|
|
ChildEl: TFresnelElement;
|
|
|
NewLeft, NewTop, NewRight, NewBottom, NewWidth, NewHeight,
|
|
|
FrameLeft, FrameRight,
|
|
|
FrameTop, FrameBottom: TFresnelLength;
|
|
|
- Size: TFresnelLayoutNode.TContentSize;
|
|
|
+ Size: TFreIntrinsicContentSize;
|
|
|
r: TFresnelRect;
|
|
|
p: TFresnelPoint;
|
|
|
begin
|
|
|
- Result.X:=0;
|
|
|
- Result.Y:=0;
|
|
|
+ Result:=Default(TFreIntrinsicContentSize);
|
|
|
|
|
|
ChildEl:=ChildNode.Element;
|
|
|
|
|
@@ -2028,7 +2060,7 @@ begin
|
|
|
NewTop:=p.y+DefaultPos.Y;
|
|
|
end;
|
|
|
|
|
|
- if Commit then
|
|
|
+ if aMode=flmMax then
|
|
|
begin
|
|
|
NewWidth:=ChildNode.Width;
|
|
|
NewHeight:=ChildNode.Height;
|
|
@@ -2040,59 +2072,67 @@ begin
|
|
|
// Note: The DeductUsedLengths has already computed simple cases
|
|
|
// e.g. given container's width and child's left and right => child's width
|
|
|
|
|
|
+ aMaxWidth:=NewWidth;
|
|
|
+ aMaxHeight:=NewHeight;
|
|
|
+ if IsNan(aMaxWidth) then
|
|
|
+ aMaxWidth:=ChildNode.MaxWidth;
|
|
|
+ if IsNan(aMaxHeight) then
|
|
|
+ aMaxHeight:=ChildNode.MaxHeight;
|
|
|
+ Size:=ChildEl.GetIntrinsicContentSize(aMode,aMaxWidth,aMaxHeight);
|
|
|
if IsNan(NewWidth) then
|
|
|
- begin
|
|
|
- if IsNan(NewHeight) then
|
|
|
- begin
|
|
|
- // auto width and height
|
|
|
- Size:=ChildNode.GetIntrinsicContentSize(aMode,ChildNode.MaxWidth,ChildNode.MaxHeight);
|
|
|
- NewWidth:=ChildNode.FitWidth(Size.Width);
|
|
|
- NewHeight:=ChildNode.FitHeight(Size.Height);
|
|
|
- end else begin
|
|
|
- // height set, width auto
|
|
|
- Size:=ChildNode.GetIntrinsicContentSize(aMode,ChildNode.MaxWidth,NewHeight);
|
|
|
- NewWidth:=ChildNode.FitWidth(Size.Width);
|
|
|
- end;
|
|
|
- end else if IsNan(NewHeight) then begin
|
|
|
- // width set, height auto
|
|
|
- Size:=ChildNode.GetIntrinsicContentSize(aMode,NewWidth,ChildNode.MaxHeight);
|
|
|
+ NewWidth:=ChildNode.FitWidth(Size.Width);
|
|
|
+ if IsNan(NewHeight) then
|
|
|
NewHeight:=ChildNode.FitHeight(Size.Height);
|
|
|
- end;
|
|
|
|
|
|
FrameLeft:=ChildNode.MarginLeft+ChildNode.BorderLeft+ChildNode.PaddingLeft;
|
|
|
FrameRight:=ChildNode.PaddingRight+ChildNode.BorderRight+ChildNode.MarginRight;
|
|
|
FrameTop:=ChildNode.MarginTop+ChildNode.BorderTop+ChildNode.PaddingTop;
|
|
|
FrameBottom:=ChildNode.PaddingBottom+ChildNode.BorderBottom+ChildNode.MarginBottom;
|
|
|
- if Commit then
|
|
|
+ if IsNan(NewLeft) then
|
|
|
begin
|
|
|
- if IsNan(NewLeft) then
|
|
|
- begin
|
|
|
- if IsNan(aMaxWidth) or IsNan(NewRight) then
|
|
|
- NewLeft:=0
|
|
|
- else
|
|
|
- NewLeft:=aMaxWidth-NewRight-NewWidth-FrameLeft-FrameRight;
|
|
|
- end;
|
|
|
- if IsNan(NewTop) then
|
|
|
- begin
|
|
|
- if IsNan(aMaxHeight) or IsNan(NewBottom) then
|
|
|
- NewTop:=0
|
|
|
- else
|
|
|
- NewTop:=aMaxHeight-NewBottom-NewHeight-FrameTop-FrameBottom;
|
|
|
- end;
|
|
|
+ if IsNan(aMaxWidth) or IsNan(NewRight) then
|
|
|
+ NewLeft:=0
|
|
|
+ else
|
|
|
+ NewLeft:=aMaxWidth-NewRight-NewWidth-FrameLeft-FrameRight;
|
|
|
+ end;
|
|
|
+ if IsNan(NewTop) then
|
|
|
+ begin
|
|
|
+ if IsNan(aMaxHeight) or IsNan(NewBottom) then
|
|
|
+ NewTop:=0
|
|
|
+ else
|
|
|
+ NewTop:=aMaxHeight-NewBottom-NewHeight-FrameTop-FrameBottom;
|
|
|
end;
|
|
|
|
|
|
// compute right, bottom of marginbox
|
|
|
- Result.X:=FrameLeft+NewWidth+FrameRight;
|
|
|
+ Result.Width:=FrameLeft+NewWidth+FrameRight;
|
|
|
if not IsNan(NewLeft) then
|
|
|
- Result.X:=Result.X+NewLeft;
|
|
|
+ Result.Width:=Result.Width+NewLeft;
|
|
|
if not IsNan(NewRight) then
|
|
|
- Result.X:=Result.X+NewRight;
|
|
|
+ Result.Width:=Result.Width+NewRight;
|
|
|
+ Result.ScrollWidth:=Result.Width;
|
|
|
+ if Size.ScrollWidth>NewWidth then
|
|
|
+ begin
|
|
|
+ Result.ScrollWidth:=FrameLeft+Result.ScrollWidth;
|
|
|
+ if not IsNan(NewLeft) then
|
|
|
+ Result.ScrollWidth:=Result.ScrollWidth+NewLeft;
|
|
|
+ if Result.ScrollWidth<Result.Width then
|
|
|
+ Result.ScrollWidth:=Result.Width;
|
|
|
+ end;
|
|
|
|
|
|
- Result.Y:=FrameTop+NewWidth+FrameBottom;
|
|
|
+ Result.Height:=FrameTop+NewWidth+FrameBottom;
|
|
|
if not IsNan(NewTop) then
|
|
|
- Result.Y:=Result.Y+NewTop;
|
|
|
+ Result.Height:=Result.Height+NewTop;
|
|
|
if not IsNan(NewBottom) then
|
|
|
- Result.Y:=Result.Y+NewBottom;
|
|
|
+ Result.Height:=Result.Height+NewBottom;
|
|
|
+ Result.ScrollHeight:=Result.Height;
|
|
|
+ if Size.ScrollHeight>NewHeight then
|
|
|
+ begin
|
|
|
+ Result.ScrollHeight:=FrameTop+Result.ScrollHeight;
|
|
|
+ if not IsNan(NewTop) then
|
|
|
+ Result.ScrollHeight:=Result.ScrollHeight+NewTop;
|
|
|
+ if Result.ScrollHeight<Result.Height then
|
|
|
+ Result.ScrollHeight:=Result.Height;
|
|
|
+ end;
|
|
|
|
|
|
if Commit then
|
|
|
begin
|