mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-08 05:58:15 +02:00
LCL: Refactor ChildSizing. Fix constraint handling.
This commit is contained in:
parent
db6ed214b9
commit
22881f66db
@ -84,6 +84,7 @@ type
|
||||
Control: TControl; // the Control of a leaf node
|
||||
MinimumSize: array[TAutoSizeBoxOrientation] of integer;
|
||||
MaximumSize: array[TAutoSizeBoxOrientation] of integer; // 0 means inifinte
|
||||
LimitedSize: array[TAutoSizeBoxOrientation] of boolean; // Was force set by Max or Min
|
||||
PreferredSize: array[TAutoSizeBoxOrientation] of integer;// without theme space
|
||||
LeftTop: array[TAutoSizeBoxOrientation] of integer;
|
||||
BorderLeftTop: array[TAutoSizeBoxOrientation] of integer;
|
||||
@ -1767,7 +1768,7 @@ type
|
||||
var
|
||||
EnlargeStyle: TChildControlResizeStyle;
|
||||
ShrinkStyle: TChildControlResizeStyle;
|
||||
CurSize: LongInt;
|
||||
CurSize, CurSpacing, CurrentMinimumSizeSum: LongInt;
|
||||
|
||||
function GetChildTotalSize: integer;
|
||||
// computes the total preferred size of all children of this Orientation
|
||||
@ -1777,10 +1778,14 @@ var
|
||||
s: LongInt;
|
||||
begin
|
||||
Result:=0;
|
||||
CurSpacing := 0;
|
||||
CurrentMinimumSizeSum := 0;
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if i=0 then
|
||||
if i=0 then begin
|
||||
inc(Result,Child.BorderLeftTop[Orientation]);
|
||||
inc(CurSpacing,Child.BorderLeftTop[Orientation]);
|
||||
end;
|
||||
if Child.PreferredSize[Orientation]<1 then
|
||||
Child.PreferredSize[Orientation]:=1;
|
||||
inc(Result,Child.PreferredSize[Orientation]);
|
||||
@ -1788,451 +1793,414 @@ var
|
||||
if i<ChildCount[Orientation]-1 then
|
||||
s:=Max(s,Children[Orientation][i+1].BorderLeftTop[Orientation]);
|
||||
inc(Result,s);
|
||||
inc(CurSpacing,s);
|
||||
inc(CurrentMinimumSizeSum,Child.MinimumSize[Orientation]);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GetChildMaxResize(out Factor: TResizeFactor;
|
||||
out ResizeableCount, ResizableSize: integer);
|
||||
// returns the number of children/gaps, that can grow (ResizeableCount)
|
||||
// and the maximum factor, by which the children/gaps can grow (TResizeFactor)
|
||||
|
||||
procedure SimplifySpacing;
|
||||
var
|
||||
i: Integer;
|
||||
CurScale: Double;
|
||||
CurOffset: LongInt;
|
||||
Child: TAutoSizeBox;
|
||||
begin
|
||||
Factor.Scale:=0;
|
||||
Factor.Offset:=0;
|
||||
ResizeableCount:=0;
|
||||
ResizableSize:=TargetSize;
|
||||
for i:=0 to ChildCount[Orientation]-2 do begin
|
||||
Children[Orientation][i].BorderRightBottom[Orientation]:=Max(
|
||||
Children[Orientation][i].BorderRightBottom[Orientation],
|
||||
Children[Orientation][i+1].BorderLeftTop[Orientation]
|
||||
);
|
||||
Children[Orientation][i+1].BorderLeftTop[Orientation]:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure EnlargeChilds;
|
||||
var
|
||||
i: Integer;
|
||||
Child: TAutoSizeBox;
|
||||
RemainingTargetSize, RemainingCurSize, NonResizeableCount: Integer;
|
||||
ScaleChanged: Boolean;
|
||||
CurScale, CurOffset: Double;
|
||||
NewSizeEx, NewSizeCarry: Double;
|
||||
NewSize, OldSize, DiffSize: Integer;
|
||||
begin
|
||||
case EnlargeStyle of
|
||||
|
||||
crsAnchorAligning:
|
||||
exit; // no resizing
|
||||
|
||||
crsScaleChilds,crsHomogenousChildResize:
|
||||
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if (Child.MaximumSize[Orientation]>0)
|
||||
and (Child.PreferredSize[Orientation]>=Child.MaximumSize[Orientation])
|
||||
then begin
|
||||
// this child can not be further enlarged
|
||||
continue;
|
||||
end;
|
||||
inc(ResizeableCount);
|
||||
|
||||
case EnlargeStyle of
|
||||
|
||||
crsScaleChilds, crsHomogenousChildResize:
|
||||
begin
|
||||
if Child.MaximumSize[Orientation]=0 then begin
|
||||
CurScale:=double(TargetSize);
|
||||
CurOffset:=TargetSize;
|
||||
end else begin
|
||||
CurScale:=double(Child.MaximumSize[Orientation])
|
||||
/Child.PreferredSize[Orientation];
|
||||
CurOffset:=Child.MaximumSize[Orientation]
|
||||
-Child.PreferredSize[Orientation];
|
||||
end;
|
||||
if (Factor.Offset=0) or (Factor.Offset>CurOffset) then begin
|
||||
Factor.Scale:=CurScale;
|
||||
Factor.Offset:=CurOffset;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
crsSameSize:
|
||||
begin
|
||||
Factor.Offset:=1; // prevent abort
|
||||
if ChildCount[Orientation] > 0 then
|
||||
CurOffset := TargetSize div ChildCount[Orientation];
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if (Child.MaximumSize[Orientation]>0)
|
||||
and (CurOffset>=Child.MaximumSize[Orientation])
|
||||
then begin
|
||||
// this childs size will be set to its MaximumSize
|
||||
ResizableSize:=ResizableSize - Child.MaximumSize[Orientation];
|
||||
continue;
|
||||
end;
|
||||
if (CurOffset<=Child.MinimumSize[Orientation])
|
||||
then begin
|
||||
// this childs size will be set to its MinimumSize
|
||||
ResizableSize:=ResizableSize - Child.MinimumSize[Orientation];
|
||||
continue;
|
||||
end;
|
||||
inc(ResizeableCount);
|
||||
end;
|
||||
end;
|
||||
|
||||
crsHomogenousSpaceResize:
|
||||
if ChildCount[Orientation]>0 then begin
|
||||
Factor.Scale:=double(TargetSize);
|
||||
Factor.Offset:=TargetSize;
|
||||
ResizeableCount:=ChildCount[Orientation]+1;
|
||||
end;
|
||||
|
||||
else
|
||||
raise Exception.Create('TAutoSizeBox.ResizeChilds');
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure EnlargeChilds(const Factor: TResizeFactor; ResizeableCount, ResizableSize: integer);
|
||||
var
|
||||
i: Integer;
|
||||
Child: TAutoSizeBox;
|
||||
DiffSize: Integer;
|
||||
NewSize: LongInt;
|
||||
OldSize: LongInt;
|
||||
begin
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
if (TargetSize=CurSize) and (EnlargeStyle<>crsSameSize) then break;
|
||||
|
||||
Child:=Children[Orientation][i];
|
||||
if (EnlargeStyle<>crsSameSize)
|
||||
and (Child.MaximumSize[Orientation]<0)
|
||||
and (Child.PreferredSize[Orientation]>=Child.MaximumSize[Orientation])
|
||||
then begin
|
||||
// this child can not be further enlarged
|
||||
continue;
|
||||
end;
|
||||
|
||||
case EnlargeStyle of
|
||||
|
||||
crsScaleChilds:
|
||||
crsScaleChilds, crsHomogenousChildResize, crsSameSize:
|
||||
begin
|
||||
// scale PreferredSize
|
||||
DiffSize:=TargetSize-CurSize;
|
||||
OldSize:=Child.PreferredSize[Orientation];
|
||||
NewSize:=round(double(OldSize)*Factor.Scale);
|
||||
NewSize:=Min(OldSize+DiffSize,Max(OldSize+1,NewSize));
|
||||
inc(CurSize,NewSize-OldSize);
|
||||
Child.PreferredSize[Orientation]:=NewSize;
|
||||
RemainingTargetSize := Max(0, TargetSize-CurSpacing);
|
||||
RemainingCurSize := Max(0, CurSize-CurSpacing);
|
||||
NonResizeableCount := 0;
|
||||
|
||||
if EnlargeStyle = crsSameSize then begin
|
||||
(* First check for any cells forced bigger by there MinSize
|
||||
This only happens for crsSameSize (because even if the total
|
||||
area grows, individual cells may shrink, if there
|
||||
PreferredSize is above the average)
|
||||
If they take extra space, then other cells that would have hit
|
||||
there MaxSize, may stay below it.
|
||||
In the "MaxSize Loop" the scale will only grow, so no further
|
||||
MinSize hits can happen there.
|
||||
*)
|
||||
if ChildCount[Orientation] > NonResizeableCount then
|
||||
NewSize := RemainingTargetSize div (ChildCount[Orientation] - NonResizeableCount);
|
||||
repeat
|
||||
ScaleChanged:=False;
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if Child.LimitedSize[Orientation] then
|
||||
continue;
|
||||
|
||||
if (NewSize<=Child.MinimumSize[Orientation])
|
||||
then begin
|
||||
// this childs size will be set to its MinimumSize
|
||||
RemainingTargetSize:=RemainingTargetSize - Child.MinimumSize[Orientation];
|
||||
RemainingCurSize:=RemainingCurSize - Child.PreferredSize[Orientation];
|
||||
Child.PreferredSize[Orientation]:=Child.MinimumSize[Orientation];
|
||||
Child.LimitedSize[Orientation] := True;
|
||||
inc(NonResizeableCount);
|
||||
OldSize := NewSize;
|
||||
if ChildCount[Orientation] > NonResizeableCount then
|
||||
NewSize := RemainingTargetSize div (ChildCount[Orientation] - NonResizeableCount)
|
||||
else
|
||||
break;
|
||||
ScaleChanged := OldSize <> NewSize;
|
||||
if ScaleChanged then
|
||||
break; // for i :=
|
||||
end;
|
||||
end;
|
||||
until (not ScaleChanged) or (RemainingCurSize<=0);
|
||||
if RemainingCurSize<=0 then
|
||||
exit;
|
||||
end;
|
||||
|
||||
repeat
|
||||
ScaleChanged:=False;
|
||||
case EnlargeStyle of
|
||||
crsScaleChilds: begin
|
||||
CurScale := double(RemainingTargetSize)/double(RemainingCurSize);
|
||||
CurOffset := 0;
|
||||
end;
|
||||
crsHomogenousChildResize: begin
|
||||
if ChildCount[Orientation] > NonResizeableCount then
|
||||
CurOffset := double(RemainingTargetSize - RemainingCurSize) / (ChildCount[Orientation] - NonResizeableCount);
|
||||
CurScale := 1;
|
||||
end;
|
||||
crsSameSize: begin
|
||||
if ChildCount[Orientation] > NonResizeableCount then
|
||||
CurOffset := double(RemainingTargetSize) / (ChildCount[Orientation] - NonResizeableCount);
|
||||
CurScale := 0;
|
||||
end;
|
||||
end;
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if Child.LimitedSize[Orientation] or (Child.MaximumSize[Orientation]=0) then
|
||||
continue;
|
||||
|
||||
NewSize:=Round(double(Child.PreferredSize[Orientation])*CurScale+CurOffset);
|
||||
if (Child.MaximumSize[Orientation]>0)
|
||||
and (NewSize>=Child.MaximumSize[Orientation])
|
||||
then begin
|
||||
// this childs size will be set to its MaximumSize
|
||||
RemainingTargetSize:=RemainingTargetSize - Child.MaximumSize[Orientation];
|
||||
RemainingCurSize:=RemainingCurSize - Child.PreferredSize[Orientation];
|
||||
Child.PreferredSize[Orientation]:=Child.MaximumSize[Orientation];
|
||||
Child.LimitedSize[Orientation] := True;
|
||||
inc(NonResizeableCount);
|
||||
ScaleChanged := True;
|
||||
break; // for i :=
|
||||
end;
|
||||
end;
|
||||
until (not ScaleChanged) or (RemainingCurSize<=0);
|
||||
if RemainingCurSize<=0 then
|
||||
exit;
|
||||
|
||||
DiffSize := RemainingTargetSize - RemainingCurSize;
|
||||
NewSizeCarry := 0;
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if Child.LimitedSize[Orientation] then
|
||||
continue;
|
||||
|
||||
OldSize:=Child.PreferredSize[Orientation];
|
||||
NewSizeEx:=double(OldSize)*CurScale+CurOffset+NewSizeCarry;
|
||||
NewSize:=Round(NewSizeEx);
|
||||
if NewSize >= 1 then NewSizeCarry:=NewSizeEx - NewSize
|
||||
else NewSizeCarry:=0;
|
||||
if i = ChildCount[Orientation] - 1 then
|
||||
NewSize:=OldSize+DiffSize
|
||||
else
|
||||
if (EnlargeStyle = crsSameSize) then
|
||||
NewSize:=Max(1,NewSize)
|
||||
else
|
||||
NewSize:=Min(OldSize+DiffSize, Max(1,NewSize));
|
||||
assert((Child.MaximumSize[Orientation]=0) or (NewSize<=Child.MaximumSize[Orientation]), 'EnlargeChilds: (Child.MaximumSize[Orientation]=0) or (NewSize<=Child.MaximumSize[Orientation])');
|
||||
assert((NewSize>=Child.MinimumSize[Orientation]), 'EnlargeChilds: (NewSize>=Child.MinimumSize[Orientation])');
|
||||
|
||||
dec(DiffSize,NewSize-OldSize);
|
||||
Child.PreferredSize[Orientation]:=NewSize;
|
||||
end;
|
||||
assert(DiffSize = 0, 'EnlargeChilds: DiffSize = 0');
|
||||
end;
|
||||
|
||||
crsHomogenousChildResize:
|
||||
begin
|
||||
// add to PreferredSize
|
||||
DiffSize:=TargetSize-CurSize;
|
||||
OldSize:=Child.PreferredSize[Orientation];
|
||||
NewSize:=Min(OldSize+Factor.Offset,OldSize+DiffSize);
|
||||
inc(CurSize,NewSize-OldSize);
|
||||
Child.PreferredSize[Orientation]:=NewSize;
|
||||
end;
|
||||
|
||||
|
||||
crsHomogenousSpaceResize:
|
||||
begin
|
||||
if i=0 then begin
|
||||
// add to left/top border
|
||||
SimplifySpacing;
|
||||
CurOffset := (TargetSize-CurSize) / (ChildCount[Orientation]+1);
|
||||
if CurOffset < 1 then
|
||||
CurOffset := 1;
|
||||
NewSizeCarry := 0;
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if i=0 then begin
|
||||
// add to left/top border
|
||||
OldSize:=Child.BorderLeftTop[Orientation];
|
||||
NewSizeEx:=double(OldSize)+CurOffset+NewSizeCarry;
|
||||
NewSize:=Round(NewSizeEx);
|
||||
NewSizeCarry:=NewSizeEx - NewSize;
|
||||
DiffSize:=TargetSize-CurSize;
|
||||
NewSize:=Min(NewSize,OldSize+DiffSize);
|
||||
inc(CurSize,NewSize-OldSize);
|
||||
Child.BorderLeftTop[Orientation]:=NewSize;
|
||||
end;
|
||||
// add to right/bottom border
|
||||
OldSize:=Child.BorderRightBottom[Orientation];
|
||||
NewSizeEx:=double(OldSize)+CurOffset+NewSizeCarry;
|
||||
NewSize:=Round(NewSizeEx);
|
||||
NewSizeCarry:=NewSizeEx - NewSize;
|
||||
DiffSize:=TargetSize-CurSize;
|
||||
OldSize:=Child.BorderLeftTop[Orientation];
|
||||
NewSize:=Min(OldSize+Factor.Offset,OldSize+DiffSize);
|
||||
NewSize:=Min(NewSize,OldSize+DiffSize);
|
||||
inc(CurSize,NewSize-OldSize);
|
||||
Child.BorderLeftTop[Orientation]:=NewSize;
|
||||
Child.BorderRightBottom[Orientation]:=NewSize;
|
||||
end;
|
||||
// add to right/bottom border
|
||||
DiffSize:=TargetSize-CurSize;
|
||||
OldSize:=Child.BorderRightBottom[Orientation];
|
||||
NewSize:=Min(OldSize+Factor.Offset,OldSize+DiffSize);
|
||||
inc(CurSize,NewSize-OldSize);
|
||||
Child.BorderRightBottom[Orientation]:=NewSize;
|
||||
if i<ChildCount[Orientation]-1 then
|
||||
Child.BorderLeftTop[Orientation]:=NewSize;
|
||||
end;
|
||||
|
||||
crsSameSize:
|
||||
begin
|
||||
OldSize:=Child.PreferredSize[Orientation];
|
||||
if ResizeableCount <= 1 then
|
||||
NewSize:=Max(1,OldSize+TargetSize-CurSize)
|
||||
else
|
||||
NewSize:=Max(1,round(double(ResizableSize)/ResizeableCount));
|
||||
if (Child.MaximumSize[Orientation] > 0) and (NewSize >= Child.MaximumSize[Orientation]) then begin
|
||||
NewSize := Child.MaximumSize[Orientation];
|
||||
end
|
||||
else
|
||||
if (NewSize <= Child.MinimumSize[Orientation]) then begin
|
||||
NewSize := Child.MinimumSize[Orientation];
|
||||
end
|
||||
else begin
|
||||
dec(ResizableSize,NewSize);
|
||||
dec(ResizeableCount);
|
||||
end;
|
||||
inc(CurSize,NewSize-OldSize);
|
||||
Child.PreferredSize[Orientation]:=NewSize;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GetChildMinResize(out Factor: TResizeFactor;
|
||||
out ResizeableCount, ResizableSize: integer);
|
||||
// returns the number of children/gaps, that can shrink (ResizeableCount)
|
||||
// and the maximum factor, by which the children/gaps can shrink (TResizeFactor)
|
||||
procedure ShrinkChilds;
|
||||
var
|
||||
i: Integer;
|
||||
CurScale: Double;
|
||||
CurOffset: LongInt;
|
||||
Child: TAutoSizeBox;
|
||||
RemainingTargetSize, RemainingCurSize, NonResizeableCount: Integer;
|
||||
ScaleChanged, LeftMostSpaceLimited: Boolean;
|
||||
CurScale, CurOffset: Double;
|
||||
NewSizeEx, NewSizeCarry: Double;
|
||||
NewSize, OldSize, DiffSize: Integer;
|
||||
begin
|
||||
Factor.Scale:=0;
|
||||
Factor.Offset:=0;
|
||||
ResizeableCount:=0;
|
||||
ResizableSize:=TargetSize;
|
||||
case ShrinkStyle of
|
||||
|
||||
crsAnchorAligning:
|
||||
exit; // no resizing
|
||||
|
||||
crsScaleChilds,crsHomogenousChildResize:
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if (Child.PreferredSize[Orientation]<=Child.MinimumSize[Orientation])
|
||||
or (Child.PreferredSize[Orientation]<=1)
|
||||
then begin
|
||||
// this child can not be further shrinked
|
||||
continue;
|
||||
end;
|
||||
inc(ResizeableCount);
|
||||
|
||||
case ShrinkStyle of
|
||||
|
||||
crsScaleChilds:
|
||||
begin
|
||||
CurScale:=double(Child.MinimumSize[Orientation])
|
||||
/Child.PreferredSize[Orientation];
|
||||
CurOffset:=Child.PreferredSize[Orientation]
|
||||
-Child.MinimumSize[Orientation];
|
||||
if (Factor.Offset=0) or (Factor.Scale<CurScale) then begin
|
||||
Factor.Scale:=CurScale;
|
||||
Factor.Offset:=CurOffset;
|
||||
end;
|
||||
end;
|
||||
|
||||
crsHomogenousChildResize:
|
||||
begin
|
||||
CurScale:=double(Child.MinimumSize[Orientation])
|
||||
/Child.PreferredSize[Orientation];
|
||||
CurOffset:=Child.PreferredSize[Orientation]
|
||||
-Child.MinimumSize[Orientation];
|
||||
if (Factor.Offset=0) or (Factor.Offset>CurOffset) then begin
|
||||
Factor.Scale:=CurScale;
|
||||
Factor.Offset:=CurOffset;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
crsSameSize:
|
||||
begin
|
||||
Factor.Offset:=1; // prevent abort
|
||||
if ChildCount[Orientation] > 0 then
|
||||
CurOffset := TargetSize div ChildCount[Orientation];
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if (Child.MaximumSize[Orientation]>0)
|
||||
and (CurOffset>=Child.MaximumSize[Orientation])
|
||||
then begin
|
||||
// this childs size will be set to its MaximumSize
|
||||
ResizableSize:=ResizableSize - Child.MaximumSize[Orientation];
|
||||
continue;
|
||||
end;
|
||||
if (CurOffset<=Child.MinimumSize[Orientation])
|
||||
then begin
|
||||
// this childs size will be set to its MinimumSize
|
||||
ResizableSize:=ResizableSize - Child.MinimumSize[Orientation];
|
||||
continue;
|
||||
end;
|
||||
inc(ResizeableCount);
|
||||
end;
|
||||
end;
|
||||
|
||||
crsHomogenousSpaceResize:
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if i=0 then begin
|
||||
CurScale:=double(TargetSize);
|
||||
CurOffset:=Child.BorderLeftTop[Orientation];
|
||||
if CurOffset>0 then begin
|
||||
inc(ResizeableCount);
|
||||
if (Factor.Offset=0) or (Factor.Offset>CurOffset) then begin
|
||||
Factor.Scale:=CurScale;
|
||||
Factor.Offset:=CurOffset;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
CurScale:=double(TargetSize);
|
||||
CurOffset:=Child.BorderRightBottom[Orientation];
|
||||
if CurOffset>0 then begin
|
||||
inc(ResizeableCount);
|
||||
if (Factor.Offset=0) or (Factor.Offset>CurOffset) then begin
|
||||
Factor.Scale:=CurScale;
|
||||
Factor.Offset:=CurOffset;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
else
|
||||
raise Exception.Create('TAutoSizeBox.ResizeChilds');
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ShrinkChilds(const Factor: TResizeFactor; ResizeableCount, ResizableSize: integer);
|
||||
var
|
||||
i: Integer;
|
||||
Child: TAutoSizeBox;
|
||||
DiffSize: Integer;
|
||||
NewSize: LongInt;
|
||||
OldSize: LongInt;
|
||||
begin
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if (ShrinkStyle<>crsSameSize)
|
||||
and ( (Child.PreferredSize[Orientation]<=1)
|
||||
or (Child.PreferredSize[Orientation]<=Child.MinimumSize[Orientation]) )
|
||||
then begin
|
||||
// this child can not be further shrinked
|
||||
continue;
|
||||
end;
|
||||
|
||||
case ShrinkStyle of
|
||||
|
||||
crsScaleChilds:
|
||||
crsScaleChilds, crsHomogenousChildResize, crsSameSize:
|
||||
begin
|
||||
// scale PreferredSize
|
||||
DiffSize:=CurSize-TargetSize;
|
||||
OldSize:=Child.PreferredSize[Orientation];
|
||||
NewSize:=Min(round(OldSize*Factor.Scale),OldSize-1);
|
||||
NewSize:=Max(Max(1,NewSize),OldSize-DiffSize);
|
||||
dec(CurSize,OldSize-NewSize);
|
||||
Child.PreferredSize[Orientation]:=NewSize;
|
||||
end;
|
||||
RemainingTargetSize := Max(0, TargetSize-CurSpacing);
|
||||
RemainingCurSize := Max(0, CurSize-CurSpacing);
|
||||
NonResizeableCount := 0;
|
||||
|
||||
crsHomogenousChildResize:
|
||||
begin
|
||||
// add to PreferredSize
|
||||
DiffSize:=CurSize-TargetSize;
|
||||
OldSize:=Child.PreferredSize[Orientation];
|
||||
NewSize:=OldSize-Factor.Offset;
|
||||
NewSize:=Max(Max(NewSize,1),OldSize-DiffSize);
|
||||
dec(CurSize,OldSize-NewSize);
|
||||
Child.PreferredSize[Orientation]:=NewSize;
|
||||
if ShrinkStyle = crsSameSize then begin
|
||||
(* First check for any cells forced smaller by there MaxSize
|
||||
This only happens for crsSameSize (because even if the total
|
||||
area shrinks, individual cells may grow, if there
|
||||
PreferredSize is below the average)
|
||||
If they take less space, then other cells that would have hit
|
||||
there MinSize, may stay above it.
|
||||
In the "MinSize Loop" the scale will only shrink, so no further
|
||||
MaxSize hits can happen there.
|
||||
*)
|
||||
if ChildCount[Orientation] > NonResizeableCount then
|
||||
NewSize := RemainingTargetSize div (ChildCount[Orientation] - NonResizeableCount);
|
||||
repeat
|
||||
ScaleChanged:=False;
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if Child.LimitedSize[Orientation] then
|
||||
continue;
|
||||
|
||||
if (Child.MaximumSize[Orientation] > 0) and (NewSize>=Child.MaximumSize[Orientation])
|
||||
then begin
|
||||
// this childs size will be set to its MaximumSize
|
||||
RemainingTargetSize:=RemainingTargetSize - Child.MaximumSize[Orientation];
|
||||
RemainingCurSize:=RemainingCurSize - Child.PreferredSize[Orientation];
|
||||
CurrentMinimumSizeSum := CurrentMinimumSizeSum - Child.MinimumSize[Orientation];
|
||||
Child.PreferredSize[Orientation]:=Child.MaximumSize[Orientation];
|
||||
Child.LimitedSize[Orientation] := True;
|
||||
inc(NonResizeableCount);
|
||||
OldSize := NewSize;
|
||||
if ChildCount[Orientation] > NonResizeableCount then
|
||||
NewSize := RemainingTargetSize div (ChildCount[Orientation] - NonResizeableCount)
|
||||
else
|
||||
break;
|
||||
ScaleChanged := OldSize <> NewSize;
|
||||
if ScaleChanged then
|
||||
break; // for i :=
|
||||
end;
|
||||
end;
|
||||
until (not ScaleChanged) or (RemainingCurSize<=0);
|
||||
if RemainingCurSize<=0 then
|
||||
exit;
|
||||
end;
|
||||
|
||||
repeat
|
||||
ScaleChanged:=False;
|
||||
case ShrinkStyle of
|
||||
crsScaleChilds: begin
|
||||
CurScale := double(RemainingTargetSize)/double(RemainingCurSize);
|
||||
CurOffset := 0;
|
||||
end;
|
||||
crsHomogenousChildResize: begin
|
||||
// negative CurOffset
|
||||
if ChildCount[Orientation] > NonResizeableCount then
|
||||
CurOffset := double(RemainingTargetSize - RemainingCurSize) / (ChildCount[Orientation] - NonResizeableCount);
|
||||
CurScale := 1;
|
||||
end;
|
||||
crsSameSize: begin
|
||||
if ChildCount[Orientation] > NonResizeableCount then
|
||||
CurOffset := double(RemainingTargetSize) / (ChildCount[Orientation] - NonResizeableCount);
|
||||
CurScale := 0;
|
||||
end;
|
||||
end;
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if Child.LimitedSize[Orientation] then
|
||||
continue;
|
||||
|
||||
NewSize:=Round(double(Child.PreferredSize[Orientation])*CurScale+CurOffset);
|
||||
if (NewSize<=Child.MinimumSize[Orientation])
|
||||
then begin
|
||||
// this childs size will be set to its MinimumSize
|
||||
NewSize := Max(Min(1, Max(0, RemainingTargetSize-CurrentMinimumSizeSum)),Child.MinimumSize[Orientation]);
|
||||
RemainingTargetSize:=RemainingTargetSize - NewSize;
|
||||
RemainingCurSize:=RemainingCurSize - Child.PreferredSize[Orientation];
|
||||
CurrentMinimumSizeSum := CurrentMinimumSizeSum - Child.MinimumSize[Orientation];
|
||||
Child.PreferredSize[Orientation]:=NewSize;
|
||||
Child.LimitedSize[Orientation] := True;
|
||||
inc(NonResizeableCount);
|
||||
ScaleChanged := True;
|
||||
break; // for i :=
|
||||
end;
|
||||
end;
|
||||
until (not ScaleChanged) or (RemainingCurSize<=0);
|
||||
if RemainingCurSize<=0 then
|
||||
exit;
|
||||
|
||||
DiffSize := RemainingCurSize - RemainingTargetSize;
|
||||
NewSizeCarry := 0;
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if Child.LimitedSize[Orientation] then
|
||||
continue;
|
||||
|
||||
OldSize:=Child.PreferredSize[Orientation];
|
||||
NewSizeEx:=double(OldSize)*CurScale+CurOffset+NewSizeCarry;
|
||||
NewSize:=Round(NewSizeEx);
|
||||
if NewSize >= 1 then NewSizeCarry:=NewSizeEx - NewSize
|
||||
else NewSizeCarry:=0;
|
||||
if i = ChildCount[Orientation] - 1 then
|
||||
NewSize:=OldSize-DiffSize
|
||||
else
|
||||
if (ShrinkStyle = crsSameSize) then
|
||||
NewSize:=Max(1,NewSize)
|
||||
else
|
||||
NewSize:=Min(OldSize+DiffSize, Max(1,NewSize));
|
||||
assert((Child.MaximumSize[Orientation]=0) or (NewSize<=Child.MaximumSize[Orientation]), 'EnlargeChilds: (Child.MaximumSize[Orientation]=0) or (NewSize<=Child.MaximumSize[Orientation])');
|
||||
assert((NewSize>=Child.MinimumSize[Orientation]), 'EnlargeChilds: (NewSize>=Child.MinimumSize[Orientation])');
|
||||
|
||||
dec(DiffSize,OldSize-NewSize);
|
||||
Child.PreferredSize[Orientation]:=NewSize;
|
||||
end;
|
||||
assert(DiffSize=0, 'ShrinkChilds: DiffSize=0');
|
||||
end;
|
||||
|
||||
crsHomogenousSpaceResize:
|
||||
begin
|
||||
if i=0 then begin
|
||||
// add to left/top border
|
||||
DiffSize:=CurSize-TargetSize;
|
||||
OldSize:=Child.BorderLeftTop[Orientation];
|
||||
NewSize:=Max(Max(0,OldSize-Factor.Offset),OldSize-DiffSize);
|
||||
dec(CurSize,OldSize-NewSize);
|
||||
Child.BorderLeftTop[Orientation]:=NewSize;
|
||||
end;
|
||||
// add to right/bottom border
|
||||
SimplifySpacing;
|
||||
RemainingTargetSize := TargetSize;
|
||||
RemainingCurSize := CurSize;
|
||||
NonResizeableCount := 0;
|
||||
LeftMostSpaceLimited := False;
|
||||
|
||||
repeat
|
||||
ScaleChanged:=False;
|
||||
CurOffset := (RemainingCurSize-RemainingTargetSize) / (ChildCount[Orientation]-NonResizeableCount+1);
|
||||
DiffSize := Round(CurOffset);
|
||||
if (ChildCount[Orientation] > 0) and not LeftMostSpaceLimited then begin
|
||||
// add to left/top border
|
||||
Child:=Children[Orientation][0];
|
||||
OldSize:=Child.BorderLeftTop[Orientation];
|
||||
NewSize:=OldSize-DiffSize;
|
||||
if NewSize < 1 then begin
|
||||
RemainingCurSize:=RemainingCurSize - Child.BorderLeftTop[Orientation];
|
||||
Child.BorderLeftTop[Orientation]:=0;
|
||||
LeftMostSpaceLimited := True;
|
||||
inc(NonResizeableCount);
|
||||
ScaleChanged := True;
|
||||
continue;
|
||||
end;
|
||||
end;
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if Child.LimitedSize[Orientation] then
|
||||
Continue;
|
||||
// add to right/bottom border
|
||||
OldSize:=Child.BorderRightBottom[Orientation];
|
||||
NewSize:=OldSize-DiffSize;
|
||||
if NewSize < 1 then begin
|
||||
RemainingCurSize:=RemainingCurSize - Child.BorderRightBottom[Orientation];
|
||||
Child.BorderRightBottom[Orientation]:=0;
|
||||
Child.LimitedSize[Orientation] := True;
|
||||
inc(NonResizeableCount);
|
||||
ScaleChanged := True;
|
||||
break; // for i :=
|
||||
end;
|
||||
end;
|
||||
until (not ScaleChanged) or (RemainingCurSize<=0) or (ChildCount[Orientation]<=NonResizeableCount-1);
|
||||
if (RemainingCurSize<=0) or (ChildCount[Orientation]<=NonResizeableCount-1) then
|
||||
exit;
|
||||
|
||||
DiffSize:=CurSize-TargetSize;
|
||||
OldSize:=Child.BorderRightBottom[Orientation];
|
||||
NewSize:=Max(Max(0,OldSize-Factor.Offset),OldSize-DiffSize);
|
||||
dec(CurSize,OldSize-NewSize);
|
||||
Child.BorderRightBottom[Orientation]:=NewSize;
|
||||
if i<ChildCount[Orientation]-1 then
|
||||
NewSizeCarry := 0;
|
||||
if (ChildCount[Orientation] > 0) and not LeftMostSpaceLimited then begin
|
||||
// add to left/top border
|
||||
Child:=Children[Orientation][0];
|
||||
OldSize:=Child.BorderLeftTop[Orientation];
|
||||
NewSizeEx:=double(OldSize)-CurOffset+NewSizeCarry;
|
||||
NewSize:=Round(NewSizeEx);
|
||||
NewSizeCarry:=NewSizeEx - NewSize;
|
||||
NewSize:=Max(NewSize,OldSize-DiffSize);
|
||||
dec(DiffSize,OldSize-NewSize);
|
||||
Child.BorderLeftTop[Orientation]:=NewSize;
|
||||
end;
|
||||
for i:=0 to ChildCount[Orientation]-1 do begin
|
||||
Child:=Children[Orientation][i];
|
||||
if Child.LimitedSize[Orientation] then
|
||||
Continue;
|
||||
// add to right/bottom border
|
||||
OldSize:=Child.BorderRightBottom[Orientation];
|
||||
NewSizeEx:=double(OldSize)-CurOffset+NewSizeCarry;
|
||||
NewSize:=Round(NewSizeEx);
|
||||
NewSizeCarry:=NewSizeEx - NewSize;
|
||||
NewSize:=Max(NewSize,OldSize-DiffSize);
|
||||
dec(DiffSize,OldSize-NewSize);
|
||||
Child.BorderRightBottom[Orientation]:=NewSize;
|
||||
end;
|
||||
end;
|
||||
|
||||
crsSameSize:
|
||||
begin
|
||||
OldSize:=Child.PreferredSize[Orientation];
|
||||
if ResizeableCount <= 1 then
|
||||
NewSize:=Max(1,OldSize+TargetSize-CurSize)
|
||||
else
|
||||
NewSize:=Max(1,round(double(ResizableSize)/ResizeableCount));
|
||||
if (Child.MaximumSize[Orientation] > 0) and (NewSize >= Child.MaximumSize[Orientation]) then begin
|
||||
NewSize := Child.MaximumSize[Orientation];
|
||||
end
|
||||
else
|
||||
if (NewSize <= Child.MinimumSize[Orientation]) then begin
|
||||
NewSize := Child.MinimumSize[Orientation];
|
||||
end
|
||||
else begin
|
||||
dec(ResizableSize,NewSize);
|
||||
dec(ResizeableCount);
|
||||
end;
|
||||
dec(CurSize,OldSize-NewSize);
|
||||
Child.PreferredSize[Orientation]:=NewSize;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
MaxResizeFactorPerItem, MinResizeFactorPerItem, CurScale: TResizeFactor;
|
||||
ResizeableCount, ResizableSize: integer;
|
||||
i: Integer;
|
||||
begin
|
||||
CurSize:=GetChildTotalSize;
|
||||
//DebugLn('TAutoSizeBox.ResizeChilds CurSize=',dbgs(CurSize),' TargetSize=',dbgs(TargetSize));
|
||||
EnlargeStyle:=crsAnchorAligning;
|
||||
ShrinkStyle:=crsAnchorAligning;
|
||||
i:=0;
|
||||
if TargetSize>CurSize then begin
|
||||
if TargetSize>=CurSize then begin
|
||||
// enlarge
|
||||
if Orientation=asboHorizontal then
|
||||
EnlargeStyle:=ChildSizing.EnlargeHorizontal
|
||||
else
|
||||
EnlargeStyle:=ChildSizing.EnlargeVertical;
|
||||
while TargetSize>CurSize do begin
|
||||
// shrink children
|
||||
GetChildMaxResize(MaxResizeFactorPerItem,ResizeableCount, ResizableSize);
|
||||
if (ResizeableCount=0) or (MaxResizeFactorPerItem.Offset=0) then break;
|
||||
|
||||
CurScale.Scale:=(double(TargetSize)/CurSize);
|
||||
if (MaxResizeFactorPerItem.Scale>0)
|
||||
and (MaxResizeFactorPerItem.Scale<CurScale.Scale) then
|
||||
CurScale.Scale:=MaxResizeFactorPerItem.Scale;
|
||||
|
||||
CurScale.Offset:=((TargetSize-CurSize-1) div ResizeableCount)+1;
|
||||
// note: the above formula makes sure, that Offset>0
|
||||
if (MaxResizeFactorPerItem.Offset>0)
|
||||
and (MaxResizeFactorPerItem.Offset<CurScale.Offset) then
|
||||
CurScale.Offset:=MaxResizeFactorPerItem.Offset;
|
||||
|
||||
EnlargeChilds(CurScale, ResizeableCount, ResizableSize);
|
||||
inc(i);
|
||||
if i>1000 then RaiseGDBException('TAutoSizeBox.ResizeChilds consistency error');
|
||||
end;
|
||||
// grow children
|
||||
if (TargetSize>CurSize) or (EnlargeStyle=crsSameSize) then
|
||||
EnlargeChilds;
|
||||
end else if TargetSize<CurSize then begin
|
||||
// shrink
|
||||
if Orientation=asboHorizontal then
|
||||
ShrinkStyle:=ChildSizing.ShrinkHorizontal
|
||||
else
|
||||
ShrinkStyle:=ChildSizing.ShrinkVertical;
|
||||
while TargetSize<CurSize do begin
|
||||
GetChildMinResize(MinResizeFactorPerItem,ResizeableCount, ResizableSize);
|
||||
if (ResizeableCount=0) or (MinResizeFactorPerItem.Offset=0) then break;
|
||||
|
||||
CurScale.Scale:=(double(TargetSize)/CurSize);
|
||||
if (MinResizeFactorPerItem.Scale>0)
|
||||
and (MinResizeFactorPerItem.Scale>CurScale.Scale) then
|
||||
CurScale.Scale:=MinResizeFactorPerItem.Scale;
|
||||
|
||||
CurScale.Offset:=((CurSize-TargetSize-1) div ResizeableCount)+1;
|
||||
// note: the above formula makes sure, that Offset>0
|
||||
if (MinResizeFactorPerItem.Offset>0)
|
||||
and (MinResizeFactorPerItem.Offset>CurScale.Offset) then
|
||||
CurScale.Offset:=MinResizeFactorPerItem.Offset;
|
||||
|
||||
ShrinkChilds(CurScale, ResizeableCount, ResizableSize);
|
||||
inc(i);
|
||||
if i>1000 then RaiseGDBException('TAutoSizeBox.ResizeChilds consistency error');
|
||||
end;
|
||||
ShrinkChilds;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user