LCL: TScrollingWinControl: use GetPreferredSize to compute ranges, CalculatePreferredSize: fixed computing mix of Layout and non Layout controls, fixed using 0x0 size of TPanel

git-svn-id: trunk@25070 -
This commit is contained in:
mattias 2010-04-29 19:54:03 +00:00
parent c77f948063
commit ecc75765fe
3 changed files with 65 additions and 44 deletions

View File

@ -4841,6 +4841,7 @@ begin
PreferredHeight:=Height;
end;
{$IFDEF OldAutoSize}
// if this control is aligned adjust PreferredWidth and/or PreferredHeight
if WidthIsAnchored then begin
// the control will be expanded to maximum width
@ -4854,6 +4855,7 @@ begin
// aligning code
PreferredHeight:=Height;
end;
{$ENDIF}
// apply constraints
PreferredWidth:=Constraints.MinMaxWidth(PreferredWidth);

View File

@ -219,33 +219,45 @@ procedure TControlScrollBar.AutoCalcRange;
function IsNonAligned(Control: TControl): boolean;
begin
Result:=(Control.Align=alNone)
Result:=(Control.Align in [alNone,alCustom])
and (Control.Anchors=[akLeft,akTop])
and (Control.AnchorSide[akLeft].Control=nil)
and (Control.AnchorSide[akTop].Control=nil);
end;
procedure GetPreferredClientRect(out PreferredWidth, PreferredHeight: integer);
begin
PreferredWidth:=0;
PreferredHeight:=0;
FControl.GetPreferredSize(PreferredWidth,PreferredHeight,true);
//DebugLn(['GetPreferredClientRect ',DbgSName(FControl),' Pref=',PreferredWidth,'x',PreferredHeight]);
dec(PreferredWidth,FControl.Width-FControl.ClientWidth);
dec(PreferredHeight,FControl.Height-FControl.ClientHeight);
if PreferredWidth<0 then PreferredWidth:=0;
if PreferredHeight<0 then PreferredHeight:=0;
end;
procedure AutoCalcVRange;
var
I: Integer;
TmpRange: Longint;
c: TControl;
PreferredWidth: Integer;
PreferredHeight: Integer;
begin
TmpRange := 0;
for I := 0 to FControl.ControlCount - 1 do
begin
c:=FControl.Controls[I];
if not c.IsControlVisible then continue;
if c.Align=alCustom then continue;
if akBottom in c.Anchors then continue;
if (c.Align<>alNone) and (akBottom in AnchorAlign[c.Align]) then continue;
if (FControl.ChildSizing.Layout<>cclNone) and IsNonAligned(c) then continue;
if (akTop in c.Anchors) and
(c.AnchorSide[akTop].Control <> nil) and
(c.AnchorSide[akTop].Control <> c) then
continue;
TmpRange := Max(TmpRange, c.Top + c.Height);
GetPreferredClientRect(PreferredWidth,PreferredHeight);
TmpRange := PreferredHeight;
if not FControl.AutoSize then begin
for I := 0 to FControl.ControlCount - 1 do
begin
c:=FControl.Controls[I];
if not c.IsControlVisible then continue;
if not IsNonAligned(c) then continue;
//DebugLn(['AutoCalcVRange c=',DbgSName(c)]);
TmpRange := Max(TmpRange, c.Top + c.Height);
end;
end;
//DebugLn(['AutoCalcVRange ',DbgSName(FControl),' Bounds=',dbgs(FControl.BoundsRect),' Client=',dbgs(FControl.ClientRect),' TmpRange=',TmpRange,' pref=',PreferredWidth,'x',PreferredHeight]);
InternalSetRange(TmpRange);
end;
@ -254,21 +266,19 @@ procedure TControlScrollBar.AutoCalcRange;
i: Integer;
TmpRange : Longint;
c: TControl;
PreferredWidth: Integer;
PreferredHeight: Integer;
begin
TmpRange := 0;
for i := 0 to FControl.ControlCount - 1 do
begin
c:=FControl.Controls[I];
if not c.IsControlVisible then continue;
if c.Align=alCustom then continue;
if akRight in c.Anchors then continue;
if (c.Align<>alNone) and (akRight in AnchorAlign[c.Align]) then continue;
if (FControl.ChildSizing.Layout<>cclNone) and IsNonAligned(c) then continue;
if (akLeft in c.Anchors) and
(c.AnchorSide[akLeft].Control <> nil) and
(c.AnchorSide[akLeft].Control <> c) then
continue;
TmpRange := Max(TmpRange, c.Left + c.Width);
GetPreferredClientRect(PreferredWidth,PreferredHeight);
TmpRange := PreferredWidth;
if not FControl.AutoSize then begin
for i := 0 to FControl.ControlCount - 1 do
begin
c:=FControl.Controls[I];
if not c.IsControlVisible then continue;
if not IsNonAligned(c) then continue;
TmpRange := Max(TmpRange, c.Left + c.Width);
end;
end;
InternalSetRange(TmpRange);
end;

View File

@ -49,6 +49,13 @@ begin
end;
{$ENDIF}
function IsNotAligned(AControl: TControl): boolean;
begin
Result:=(AControl.Align=alNone)
and (AControl.Anchors=[akLeft,akTop])
and (AControl.AnchorSide[akLeft].Control=nil)
and (AControl.AnchorSide[akTop].Control=nil);
end;
{------------------------------------------------------------------------------
Autosizing Helper classes
@ -805,9 +812,7 @@ begin
Child:=WinControl.Controls[i];
ChildData:=Childs[Child];
if not ChildData.Visible then continue;
if (Child.Align=alNone)
and (Side in Child.Anchors) and (Child.AnchorSide[Side].Control=nil)
then begin
if IsNotAligned(Child) then begin
// this is a non aligned control
//DebugLn(['TAutoSizeCtrlData.DoMoveNonAlignedChilds Child=',DbgSName(Child),' Side=',dbgs(Side)]);
if FindMinimum then begin
@ -853,6 +858,7 @@ var
MoveDiff: Integer;
AlignList: TFPList;
r: TRect;
i: Integer;
begin
if ChildCount=0 then exit;
if WinControl.ChildSizing.Layout=cclNone then begin
@ -875,7 +881,11 @@ begin
Box:=nil;
AlignList:=TFPList.Create;
try
WinControl.CreateControlAlignList(alNone,AlignList,nil);
for i:=0 to WinControl.ControlCount-1 do begin
Child:=WinControl.Controls[i];
if Child.IsControlVisible and IsNotAligned(Child) then
AlignList.Add(Child);
end;
if AlignList.Count=0 then exit;
ChildSizing:=TControlChildSizing.Create(nil);
Box:=TAutoSizeBox.Create;
@ -990,7 +1000,8 @@ procedure TAutoSizeCtrlData.ComputePreferredClientArea(
if UseCurrentWidth then
NewWidth:=Child.Width
else if CurPreferredWidth>0 then
else if (CurPreferredWidth>0)
or ((CurPreferredWidth=0) and (csAutoSize0x0 in Child.ControlStyle)) then
NewWidth:=CurPreferredWidth
else
NewWidth:=Child.GetDefaultWidth;
@ -998,7 +1009,8 @@ procedure TAutoSizeCtrlData.ComputePreferredClientArea(
if UseCurrentHeight then
NewHeight:=Child.Height
else if CurPreferredHeight>0 then
else if (CurPreferredHeight>0)
or ((CurPreferredHeight=0) and (csAutoSize0x0 in Child.ControlStyle)) then
NewHeight:=CurPreferredHeight
else
NewHeight:=Child.GetDefaultHeight;
@ -1086,10 +1098,13 @@ begin
end;
end;
end;
//WriteDebugReport('anchored','');
SetupNonAlignedChilds(MoveNonAlignedChilds);
//WriteDebugReport('nonaligned','');
// setup the dependencies for Aligned controls
AlignChilds;
//WriteDebugReport('aligned','');
// setup space for dependencies
SetupSpace;
@ -2482,14 +2497,6 @@ var
end;
end;
function IsNotAligned(AControl: TControl): boolean;
begin
Result:=(AControl.Align=alNone)
and (AControl.Anchors=[akLeft,akTop])
and (AControl.AnchorSide[akLeft].Control=nil)
and (AControl.AnchorSide[akTop].Control=nil);
end;
procedure DoPosition(Control: TControl; AAlign: TAlign; AControlIndex: Integer);
var
NewLeft, NewTop, NewWidth, NewHeight: Integer;
@ -8000,7 +8007,7 @@ end;
Calculates the default/preferred width and height for a TWinControl, which is
used by the LCL autosizing algorithms as default size. Only positive values
are valid. Negative or 0 are treated as undefined and the LCL uses other sizes
instead.
instead (exception: csAutoSize0x0).
TWinControl overrides this:
If there are childs, their total preferred size is calculated.
If this value can not be computed (e.g. the childs depend too much on their
@ -8033,6 +8040,7 @@ begin
if HandleAllocated then begin
TWSWinControlClass(WidgetSetClass).GetPreferredSize(Self,
PreferredWidth, PreferredHeight, WithThemeSpace);
//DebugLn(['TWinControl.CalculatePreferredSize WidgetSet ',DbgSName(Self),' Preferred=',PreferredWidth,'x',PreferredHeight]);
end;
// check AdjustClientRect
@ -8053,6 +8061,7 @@ begin
Layout:=TAutoSizeCtrlData.Create(Self);
Layout.ComputePreferredClientArea(false,NewMoveLeft,NewMoveRight,
NewClientWidth,NewClientHeight);
//Layout.WriteDebugReport('TWinControl.CalculatePreferredSize ',' ');
if (NewMoveLeft<>0) or (NewMoveRight<>0) then ;
finally
Layout.Free;