diff --git a/lcl/controls.pp b/lcl/controls.pp index 36e393f95c..4c44337a4a 100644 --- a/lcl/controls.pp +++ b/lcl/controls.pp @@ -218,7 +218,9 @@ type csHasCancelAction, // control implements useful ExecuteCancelAction csNoDesignSelectable, // control can not be selected at design time csOwnedChildrenNotSelectable, // child controls owned by this control are NOT selectable in the designer - csAutoSize0x0 // if the preferred size is 0x0 then control is shrinked ot 0x0 + csAutoSize0x0, // if the preferred size is 0x0 then control is shrinked ot 0x0 + csAutoSizeKeepChildLeft, // when AutoSize=true do not move children horizontally + csAutoSizeKeepChildTop // when AutoSize=true do not move children vertically ); TControlStyle = set of TControlStyleType; diff --git a/lcl/forms.pp b/lcl/forms.pp index 6631950533..ca2ab73ac1 100644 --- a/lcl/forms.pp +++ b/lcl/forms.pp @@ -175,6 +175,7 @@ type procedure SetAutoScroll(Value: Boolean); virtual; procedure Loaded; override; property AutoScroll: Boolean read FAutoScroll write SetAutoScroll default False;// auto show/hide scrollbars + procedure SetAutoSize(Value: Boolean); override; public constructor Create(TheOwner : TComponent); override; destructor Destroy; override; diff --git a/lcl/include/controlscrollbar.inc b/lcl/include/controlscrollbar.inc index 28077de78c..b5c08aec96 100644 --- a/lcl/include/controlscrollbar.inc +++ b/lcl/include/controlscrollbar.inc @@ -237,58 +237,21 @@ procedure TControlScrollBar.AutoCalcRange; procedure AutoCalcVRange; var - I: Integer; - TmpRange: Longint; - c: TControl; PreferredWidth: Integer; PreferredHeight: Integer; begin - if FControl.AutoSize - or ((FControl.Parent<>nil) and (FControl.Parent.ChildSizing.Layout<>cclNone)) then - begin - GetPreferredClientRect(PreferredWidth,PreferredHeight); - TmpRange := PreferredHeight; - end - else begin - TmpRange := 0; - 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; + GetPreferredClientRect(PreferredWidth,PreferredHeight); //DebugLn(['AutoCalcVRange ',DbgSName(FControl),' AutoSize=',FControl.AutoSize,' Bounds=',dbgs(FControl.BoundsRect),' Client=',dbgs(FControl.ClientRect),' TmpRange=',TmpRange,' pref=',PreferredWidth,'x',PreferredHeight]); - InternalSetRange(TmpRange); + InternalSetRange(PreferredHeight); end; procedure AutoCalcHRange; var - i: Integer; - TmpRange : Longint; - c: TControl; PreferredWidth: Integer; PreferredHeight: Integer; begin - if FControl.AutoSize - or ((FControl.Parent<>nil) and (FControl.Parent.ChildSizing.Layout<>cclNone)) then - begin - GetPreferredClientRect(PreferredWidth,PreferredHeight); - TmpRange := PreferredWidth; - end - else begin - TmpRange := 0; - 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); + GetPreferredClientRect(PreferredWidth,PreferredHeight); + InternalSetRange(PreferredWidth); end; begin diff --git a/lcl/include/scrollingwincontrol.inc b/lcl/include/scrollingwincontrol.inc index 58c7639847..c0e1b5e19e 100644 --- a/lcl/include/scrollingwincontrol.inc +++ b/lcl/include/scrollingwincontrol.inc @@ -223,6 +223,16 @@ begin UpdateScrollbars; end; +procedure TScrollingWinControl.SetAutoSize(Value: Boolean); +begin + if AutoSize=Value then exit; + if Value then + ControlStyle:=ControlStyle-[csAutoSizeKeepChildLeft,csAutoSizeKeepChildTop] + else + ControlStyle:=ControlStyle+[csAutoSizeKeepChildLeft,csAutoSizeKeepChildTop]; + inherited SetAutoSize(Value); +end; + procedure TScrollingWinControl.WMVScroll(var Message : TLMVScroll); begin VertScrollbar.ScrollHandler(Message); @@ -242,7 +252,8 @@ begin FVertScrollbar := TControlScrollBar.Create(Self, sbVertical); FHorzScrollbar := TControlScrollBar.Create(Self, sbHorizontal); - ControlStyle := [csAcceptsControls, csClickEvents, csDoubleClicks]; + ControlStyle := [csAcceptsControls, csClickEvents, csDoubleClicks, + csAutoSizeKeepChildLeft, csAutoSizeKeepChildTop]; with GetControlClassDefaultSize do SetInitialBounds(0, 0, CX, CY); diff --git a/lcl/include/wincontrol.inc b/lcl/include/wincontrol.inc index 82948f0a20..97ce24f1dd 100644 --- a/lcl/include/wincontrol.inc +++ b/lcl/include/wincontrol.inc @@ -170,7 +170,8 @@ type function GetChildren(AControl: TControl): TAutoSizeCtrlData; procedure DoMoveNonAlignedChildren(Side: TAnchorKind; var MoveDiff: integer; FindMinimum: boolean); - procedure SetupNonAlignedChildren(MoveNonAlignedChildren: boolean); + procedure SetupNonAlignedChildren(MoveNonAlignedChildrenLeft, + MoveNonAlignedChildrenTop: boolean); procedure AlignChildren; procedure SetupSpace; function ComputePositions: boolean;// false if recomputation is needed (a property changed) @@ -188,7 +189,8 @@ type constructor Create(AControl: TControl; IsParent: boolean = true); destructor Destroy; override; procedure Clear; - procedure ComputePreferredClientArea(MoveNonAlignedChilds: boolean; + procedure ComputePreferredClientArea(MoveNonAlignedChildrenLeft, + MoveNonAlignedChildrenTop: boolean; out MoveNonAlignedToLeft, MoveNonAlignedToTop, PreferredClientWidth, PreferredClientHeight: integer); procedure FixControlProperties(Child: TControl); @@ -874,7 +876,8 @@ begin end; end; -procedure TAutoSizeCtrlData.SetupNonAlignedChildren(MoveNonAlignedChildren: boolean); +procedure TAutoSizeCtrlData.SetupNonAlignedChildren(MoveNonAlignedChildrenLeft, + MoveNonAlignedChildrenTop: boolean); var ChildSizing: TControlChildSizing; Box: TAutoSizeBox; @@ -897,12 +900,12 @@ begin MoveDiff:=0; DoMoveNonAlignedChildren(akLeft,MoveDiff,true); //DebugLn(['TAutoSizeCtrlData.ComputePreferredClientArea akLeft MoveDiff=',MoveDiff]); - if not MoveNonAlignedChildren then MoveDiff:=0; + if not MoveNonAlignedChildrenLeft then MoveDiff:=0; DoMoveNonAlignedChildren(akLeft,MoveDiff,false); MoveDiff:=0; DoMoveNonAlignedChildren(akTop,MoveDiff,true); //DebugLn(['TAutoSizeCtrlData.ComputePreferredClientArea akTop MoveDiff=',MoveDiff]); - if not MoveNonAlignedChildren then MoveDiff:=0; + if not MoveNonAlignedChildrenTop then MoveDiff:=0; DoMoveNonAlignedChildren(akTop,MoveDiff,false); end else begin // there is an automatic layout for non aligned childs @@ -960,9 +963,9 @@ begin end; procedure TAutoSizeCtrlData.ComputePreferredClientArea( - MoveNonAlignedChilds: boolean; - out MoveNonAlignedToLeft, MoveNonAlignedToTop, - PreferredClientWidth, PreferredClientHeight: integer); + MoveNonAlignedChildrenLeft, MoveNonAlignedChildrenTop: boolean; out + MoveNonAlignedToLeft, MoveNonAlignedToTop, PreferredClientWidth, + PreferredClientHeight: integer); { if MoveNonAlignedChilds=true then all non-aligned childs will be moved in parallel, so that at least one child is positioned left most and one child is positioned top most. @@ -1140,7 +1143,7 @@ begin end; //WriteDebugReport('anchored',''); - SetupNonAlignedChildren(MoveNonAlignedChilds); + SetupNonAlignedChildren(MoveNonAlignedChildrenLeft,MoveNonAlignedChildrenTop); //WriteDebugReport('nonaligned',''); // setup the dependencies for Aligned controls AlignChildren; @@ -1182,7 +1185,7 @@ begin end; // compute needed MoveNonAlignedToLeft,MoveNonAlignedToTop - if MoveNonAlignedChilds then + if MoveNonAlignedChildrenLeft or MoveNonAlignedChildrenTop then begin MoveNonAlignedToLeft:=Low(integer); MoveNonAlignedToTop:=Low(integer); @@ -1192,7 +1195,8 @@ begin ChildData:=Children[Child]; if not Child.IsControlVisible then continue; if not IsNotAligned(Child) then continue; - if (ChildData.Sides[akLeft].DistanceState[assddLeftTop]=assdfValid) then + if MoveNonAlignedChildrenLeft + and (ChildData.Sides[akLeft].DistanceState[assddLeftTop]=assdfValid) then MoveNonAlignedToLeft:=Max(MoveNonAlignedToLeft, Child.Left-ChildData.Sides[akLeft].Distance[assddLeftTop]); { the below is only correct, if PreferredClientWidth is realized. @@ -1201,7 +1205,8 @@ begin Child.Left -(PreferredClientWidth -ChildData.Sides[akLeft].Distance[assddRightBottom]));} - if (ChildData.Sides[akTop].DistanceState[assddLeftTop]=assdfValid) then + if MoveNonAlignedChildrenTop + and (ChildData.Sides[akTop].DistanceState[assddLeftTop]=assdfValid) then MoveNonAlignedToTop:=Max(MoveNonAlignedToTop, Child.Top-ChildData.Sides[akTop].Distance[assddLeftTop]); { the below is only correct, if PreferredClientWidth is realized. @@ -3254,8 +3259,10 @@ var Layout:=nil; try Layout:=TAutoSizeCtrlData.Create(Self); - Layout.ComputePreferredClientArea(true,dx,dy, - NewClientWidth,NewClientHeight); + Layout.ComputePreferredClientArea( + not (csAutoSizeKeepChildLeft in ControlStyle), + not (csAutoSizeKeepChildTop in ControlStyle), + dx,dy,NewClientWidth,NewClientHeight); if (NewClientWidth<>0) or (NewClientHeight<>0) then ; //if (dx<>0) or (dy<>0) then DebugLn(['GetMoveDiffForNonAlignedChilds ',DbgSName(Self),' dx=',dx,' dy=',dy]); finally @@ -7757,7 +7764,7 @@ begin Layout:=nil; try Layout:=TAutoSizeCtrlData.Create(Self); - Layout.ComputePreferredClientArea(false,NewMoveLeft,NewMoveRight, + Layout.ComputePreferredClientArea(false,false,NewMoveLeft,NewMoveRight, NewClientWidth,NewClientHeight); //Layout.WriteDebugReport('TWinControl.CalculatePreferredSize ',' '); if (NewMoveLeft<>0) or (NewMoveRight<>0) then ;