mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-18 15:49:27 +02:00
LCL: anchor docking: auto cleanup on undock/hiding, undocking pages, anchoring on manualfloat for non forms, fixed undocking pages, TSplitter: fixed anchor splitter max/min
git-svn-id: trunk@13760 -
This commit is contained in:
parent
84a32a76be
commit
f3efce1701
@ -35,7 +35,7 @@ object MainForm: TMainForm
|
||||
end
|
||||
object CreateLayoutGroupBox: TGroupBox
|
||||
Left = 16
|
||||
Height = 95
|
||||
Height = 200
|
||||
Top = 104
|
||||
Width = 115
|
||||
AutoSize = True
|
||||
@ -45,27 +45,55 @@ object MainForm: TMainForm
|
||||
ChildSizing.HorizontalSpacing = 6
|
||||
ChildSizing.VerticalSpacing = 6
|
||||
ChildSizing.Layout = cclLeftToRightThenTopToBottom
|
||||
ClientHeight = 76
|
||||
ClientHeight = 181
|
||||
ClientWidth = 111
|
||||
TabOrder = 2
|
||||
object TwoPagesButton: TButton
|
||||
object ClearLayoutsButton: TButton
|
||||
Left = 6
|
||||
Height = 29
|
||||
Top = 6
|
||||
Width = 99
|
||||
Caption = 'Clear Layouts'
|
||||
OnClick = ClearLayoutsButtonClick
|
||||
TabOrder = 1
|
||||
end
|
||||
object TwoSiblingsButton: TButton
|
||||
Left = 6
|
||||
Height = 29
|
||||
Top = 41
|
||||
Width = 99
|
||||
Caption = 'Two Siblings'
|
||||
OnClick = TwoSiblingsButtonClick
|
||||
TabOrder = 4
|
||||
end
|
||||
object TwoPagesButton: TButton
|
||||
Left = 6
|
||||
Height = 29
|
||||
Top = 76
|
||||
Width = 99
|
||||
AutoSize = True
|
||||
Caption = 'Two Pages'
|
||||
OnClick = TwoPagesButtonClick
|
||||
TabOrder = 0
|
||||
end
|
||||
object ClearLayoutsButton: TButton
|
||||
object ThreePagesButton: TButton
|
||||
Left = 6
|
||||
Height = 29
|
||||
Top = 41
|
||||
Top = 111
|
||||
Width = 99
|
||||
Caption = 'Clear Layouts'
|
||||
OnClick = ClearLayoutsButtonClick
|
||||
TabOrder = 1
|
||||
Caption = 'Three Pages'
|
||||
OnClick = ThreePagesButtonClick
|
||||
TabOrder = 2
|
||||
end
|
||||
object SpiralButton: TButton
|
||||
Left = 6
|
||||
Height = 29
|
||||
Top = 146
|
||||
Width = 99
|
||||
Caption = 'Spiral'
|
||||
Enabled = False
|
||||
OnClick = SpiralButtonClick
|
||||
TabOrder = 3
|
||||
end
|
||||
end
|
||||
object MainPopupMenu: TPopupMenu
|
||||
|
@ -12,15 +12,22 @@ LazarusResources.Add('TMainForm','FORMDATA',[
|
||||
+#16'SaveLayoutButton'#4'Left'#2#8#6'Height'#2#29#3'Top'#2'@'#5'Width'#3#177#0
|
||||
+#8'AutoSize'#9#7'Caption'#6#25'Save Layout to config.xml'#7'OnClick'#7#21'Sa'
|
||||
+'veLayoutButtonClick'#8'TabOrder'#2#1#0#0#9'TGroupBox'#20'CreateLayoutGroupB'
|
||||
+'ox'#4'Left'#2#16#6'Height'#2'_'#3'Top'#2'h'#5'Width'#2's'#8'AutoSize'#9#7'C'
|
||||
+'aption'#6#13'Create Layout'#28'ChildSizing.LeftRightSpacing'#2#6#28'ChildSi'
|
||||
+'zing.TopBottomSpacing'#2#6#29'ChildSizing.HorizontalSpacing'#2#6#27'ChildSi'
|
||||
+'zing.VerticalSpacing'#2#6#18'ChildSizing.Layout'#7#29'cclLeftToRightThenTop'
|
||||
+'ToBottom'#12'ClientHeight'#2'L'#11'ClientWidth'#2'o'#8'TabOrder'#2#2#0#7'TB'
|
||||
+'utton'#14'TwoPagesButton'#4'Left'#2#6#6'Height'#2#29#3'Top'#2#6#5'Width'#2
|
||||
+'c'#8'AutoSize'#9#7'Caption'#6#9'Two Pages'#7'OnClick'#7#19'TwoPagesButtonCl'
|
||||
+'ick'#8'TabOrder'#2#0#0#0#7'TButton'#18'ClearLayoutsButton'#4'Left'#2#6#6'He'
|
||||
+'ight'#2#29#3'Top'#2')'#5'Width'#2'c'#7'Caption'#6#13'Clear Layouts'#7'OnCli'
|
||||
+'ck'#7#23'ClearLayoutsButtonClick'#8'TabOrder'#2#1#0#0#0#10'TPopupMenu'#13'M'
|
||||
+'ainPopupMenu'#4'left'#3#192#0#3'top'#2#24#0#0#0
|
||||
+'ox'#4'Left'#2#16#6'Height'#3#200#0#3'Top'#2'h'#5'Width'#2's'#8'AutoSize'#9#7
|
||||
+'Caption'#6#13'Create Layout'#28'ChildSizing.LeftRightSpacing'#2#6#28'ChildS'
|
||||
+'izing.TopBottomSpacing'#2#6#29'ChildSizing.HorizontalSpacing'#2#6#27'ChildS'
|
||||
+'izing.VerticalSpacing'#2#6#18'ChildSizing.Layout'#7#29'cclLeftToRightThenTo'
|
||||
+'pToBottom'#12'ClientHeight'#3#181#0#11'ClientWidth'#2'o'#8'TabOrder'#2#2#0#7
|
||||
+'TButton'#18'ClearLayoutsButton'#4'Left'#2#6#6'Height'#2#29#3'Top'#2#6#5'Wid'
|
||||
+'th'#2'c'#7'Caption'#6#13'Clear Layouts'#7'OnClick'#7#23'ClearLayoutsButtonC'
|
||||
+'lick'#8'TabOrder'#2#1#0#0#7'TButton'#17'TwoSiblingsButton'#4'Left'#2#6#6'He'
|
||||
+'ight'#2#29#3'Top'#2')'#5'Width'#2'c'#7'Caption'#6#12'Two Siblings'#7'OnClic'
|
||||
+'k'#7#22'TwoSiblingsButtonClick'#8'TabOrder'#2#4#0#0#7'TButton'#14'TwoPagesB'
|
||||
+'utton'#4'Left'#2#6#6'Height'#2#29#3'Top'#2'L'#5'Width'#2'c'#8'AutoSize'#9#7
|
||||
+'Caption'#6#9'Two Pages'#7'OnClick'#7#19'TwoPagesButtonClick'#8'TabOrder'#2#0
|
||||
+#0#0#7'TButton'#16'ThreePagesButton'#4'Left'#2#6#6'Height'#2#29#3'Top'#2'o'#5
|
||||
+'Width'#2'c'#7'Caption'#6#11'Three Pages'#7'OnClick'#7#21'ThreePagesButtonCl'
|
||||
+'ick'#8'TabOrder'#2#2#0#0#7'TButton'#12'SpiralButton'#4'Left'#2#6#6'Height'#2
|
||||
+#29#3'Top'#3#146#0#5'Width'#2'c'#7'Caption'#6#6'Spiral'#7'Enabled'#8#7'OnCli'
|
||||
+'ck'#7#17'SpiralButtonClick'#8'TabOrder'#2#3#0#0#0#10'TPopupMenu'#13'MainPop'
|
||||
+'upMenu'#4'left'#3#192#0#3'top'#2#24#0#0#0
|
||||
]);
|
||||
|
@ -13,6 +13,9 @@ type
|
||||
{ TMainForm }
|
||||
|
||||
TMainForm = class(TForm)
|
||||
TwoSiblingsButton: TButton;
|
||||
SpiralButton: TButton;
|
||||
ThreePagesButton: TButton;
|
||||
ClearLayoutsButton: TButton;
|
||||
TwoPagesButton: TButton;
|
||||
CreateLayoutGroupBox: TGroupBox;
|
||||
@ -25,7 +28,10 @@ type
|
||||
procedure FormDestroy(Sender: TObject);
|
||||
procedure FormPaint(Sender: TObject);
|
||||
procedure SaveLayoutButtonClick(Sender: TObject);
|
||||
procedure SpiralButtonClick(Sender: TObject);
|
||||
procedure ThreePagesButtonClick(Sender: TObject);
|
||||
procedure TwoPagesButtonClick(Sender: TObject);
|
||||
procedure TwoSiblingsButtonClick(Sender: TObject);
|
||||
private
|
||||
function CreateNewForm: TCustomForm;
|
||||
procedure ClearLayout;
|
||||
@ -57,6 +63,45 @@ begin
|
||||
Config.Free;
|
||||
end;
|
||||
|
||||
procedure TMainForm.SpiralButtonClick(Sender: TObject);
|
||||
var
|
||||
Form1: TCustomForm;
|
||||
Form2: TCustomForm;
|
||||
//Form3: TCustomForm;
|
||||
//Form4: TCustomForm;
|
||||
//Form5: TCustomForm;
|
||||
begin
|
||||
debugln;
|
||||
ClearLayout;
|
||||
|
||||
Form1:=CreateNewForm;
|
||||
Form2:=CreateNewForm;
|
||||
DockingManager.Manager.InsertControl(Form2,alRight,Form1);
|
||||
//Form3:=CreateNewForm;
|
||||
//DockingManager.Manager.InsertControl(Form3,alLeft,Form1);
|
||||
//Form4:=CreateNewForm;
|
||||
//DockingManager.Manager.InsertControl(Form4,alTop,Form1);
|
||||
//Form5:=CreateNewForm;
|
||||
//DockingManager.Manager.InsertControl(Form5,alBottom,Form1);
|
||||
end;
|
||||
|
||||
procedure TMainForm.ThreePagesButtonClick(Sender: TObject);
|
||||
var
|
||||
Form1: TCustomForm;
|
||||
Form2: TCustomForm;
|
||||
Form3: TCustomForm;
|
||||
begin
|
||||
debugln;
|
||||
ClearLayout;
|
||||
|
||||
Form1:=CreateNewForm;
|
||||
Form1.Width:=500;
|
||||
Form2:=CreateNewForm;
|
||||
DockingManager.Manager.InsertControl(Form2,alClient,Form1);
|
||||
Form3:=CreateNewForm;
|
||||
DockingManager.Manager.InsertControl(Form3,alClient,Form1);
|
||||
end;
|
||||
|
||||
procedure TMainForm.TwoPagesButtonClick(Sender: TObject);
|
||||
var
|
||||
Form1: TCustomForm;
|
||||
@ -70,6 +115,19 @@ begin
|
||||
DockingManager.Manager.InsertControl(Form2,alClient,Form1);
|
||||
end;
|
||||
|
||||
procedure TMainForm.TwoSiblingsButtonClick(Sender: TObject);
|
||||
var
|
||||
Form1: TCustomForm;
|
||||
Form2: TCustomForm;
|
||||
begin
|
||||
debugln;
|
||||
ClearLayout;
|
||||
|
||||
Form1:=CreateNewForm;
|
||||
Form2:=CreateNewForm;
|
||||
DockingManager.Manager.InsertControl(Form2,alRight,Form1);
|
||||
end;
|
||||
|
||||
function TMainForm.CreateNewForm: TCustomForm;
|
||||
var
|
||||
DockForm: TDockFormX;
|
||||
@ -80,11 +138,13 @@ begin
|
||||
// connect the TLazControlDocker of the new form to our DockingManager
|
||||
// this will automatically create a unique name for the forms layout.
|
||||
DockForm.Docker.Manager:=DockingManager;
|
||||
|
||||
// assign the unique name, so that the user can distinguish the forms
|
||||
// This is only done here for demonstration purpose.
|
||||
DockForm.Name:=DockForm.Docker.DockerName;
|
||||
// To make debugging easier give each TLazControlDocker a unique name.
|
||||
DockForm.Caption:=DockForm.Name;
|
||||
DockForm.Docker.Name:='Docker'+DockForm.Name;
|
||||
|
||||
// finally: show the form
|
||||
// If a form with this layout was already shown in the past, then
|
||||
// the DockingManager will automatically restore the layout.
|
||||
@ -98,11 +158,8 @@ var
|
||||
begin
|
||||
// free all forms and layouts
|
||||
for i:=ComponentCount-1 downto 0 do begin
|
||||
if Components[i] is TDockFormX then begin
|
||||
if TDockFormX(Components[i]).Parent<>nil then
|
||||
DockingManager.Manager.UndockControl(TDockFormX(Components[i]),false);
|
||||
if Components[i] is TDockFormX then
|
||||
Components[i].Free;
|
||||
end;
|
||||
end;
|
||||
DockingManager.ClearConfigs;
|
||||
end;
|
||||
|
@ -22,14 +22,14 @@
|
||||
</RunParams>
|
||||
<RequiredPackages Count="3">
|
||||
<Item1>
|
||||
<PackageName Value="SynEdit"/>
|
||||
<PackageName Value="FCL"/>
|
||||
<MinVersion Major="1" Valid="True"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<PackageName Value="LCL"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
<PackageName Value="FCL"/>
|
||||
<PackageName Value="SynEdit"/>
|
||||
<MinVersion Major="1" Valid="True"/>
|
||||
</Item3>
|
||||
</RequiredPackages>
|
||||
|
@ -439,7 +439,7 @@ type
|
||||
end;
|
||||
|
||||
var
|
||||
DragManager: TDragManager;
|
||||
DragManager: TDragManager = nil;// created in initialization
|
||||
|
||||
type
|
||||
{ TDockManager is an abstract class for managing a dock site's docked
|
||||
|
@ -3390,7 +3390,7 @@ begin
|
||||
//debugln('TControl.Dock A ',DbgSName(Self));
|
||||
|
||||
DoDock(NewDockSite,ARect);
|
||||
|
||||
|
||||
if FHostDockSite<>NewDockSite then
|
||||
begin
|
||||
// HostDockSite has changed -> commit
|
||||
|
@ -390,7 +390,7 @@ begin
|
||||
// OffsetMaxUpper = maximum the Splitter can be moved bottom/right
|
||||
OffsetMaxUpper := Max(0,GetParentsClientSize
|
||||
-GetControlSize(Self)-GetControlMinPos(Self));
|
||||
|
||||
//DebugLn(['TCustomSplitter.MoveSplitter OffsetMaxLower=',OffsetMaxLower,' OffsetMaxUpper=',OffsetMaxUpper]);
|
||||
for i:=0 to AnchoredControlCount-1 do begin
|
||||
CurResizeControl:=AnchoredControls[i];
|
||||
//debugln('TCustomSplitter.MoveSplitter ',DbgSName(Self),' CurResizeControl=',DbgSName(CurResizeControl));
|
||||
@ -408,24 +408,32 @@ begin
|
||||
// calculate how much the CurResizeControl can be enlarged
|
||||
CurMaxEnlarge:=Max(0,GetControlConstraintsMaxSize(CurResizeControl)
|
||||
-GetControlSize(CurResizeControl));
|
||||
if CurMaxEnlarge=0 then
|
||||
if CurMaxEnlarge=0 then begin
|
||||
CurMaxEnlarge:=GetParentsClientSize;
|
||||
//debugln('TCustomSplitter.MoveSplitter ',DbgSName(Self),' CurResizeControl=',DbgSName(CurResizeControl),' CurMaxShrink=',dbgs(CurMaxShrink),' CurMaxEnlarge=',dbgs(CurMaxEnlarge),' ',dbgs(GetControlConstraintsMaxSize(CurResizeControl)));
|
||||
if GetControlMinPos(CurResizeControl)<0 then
|
||||
dec(CurMaxEnlarge,GetControlMinPos(CurResizeControl));
|
||||
end;
|
||||
//debugln('TCustomSplitter.MoveSplitter ',DbgSName(Self),' CurResizeControl=',DbgSName(CurResizeControl),' CurMaxShrink=',dbgs(CurMaxShrink),' CurMaxEnlarge=',dbgs(CurMaxEnlarge),' ConstraintsMax=',dbgs(GetControlConstraintsMaxSize(CurResizeControl)));
|
||||
|
||||
// apply to the offset boundaries
|
||||
if (CurResizeControl.AnchorSide[akLeft].Control=Self)
|
||||
or (CurResizeControl.AnchorSide[akTop].Control=Self) then begin
|
||||
OffsetMaxLower:=Min(OffsetMaxLower,CurMaxShrink);
|
||||
OffsetMaxUpper:=Min(OffsetMaxUpper,CurMaxEnlarge);
|
||||
if CurMaxShrink>0 then
|
||||
OffsetMaxLower:=Min(OffsetMaxLower,CurMaxShrink);
|
||||
if CurMaxEnlarge>0 then
|
||||
OffsetMaxUpper:=Min(OffsetMaxUpper,CurMaxEnlarge);
|
||||
end else begin
|
||||
OffsetMaxLower:=Min(OffsetMaxLower,CurMaxEnlarge);
|
||||
OffsetMaxUpper:=Min(OffsetMaxUpper,CurMaxShrink);
|
||||
if CurMaxEnlarge>0 then
|
||||
OffsetMaxLower:=Min(OffsetMaxLower,CurMaxEnlarge);
|
||||
if CurMaxShrink>0 then
|
||||
OffsetMaxUpper:=Min(OffsetMaxUpper,CurMaxShrink);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// apply the offset boundaries to the offset
|
||||
Offset:=Max(Min(Offset,OffsetMaxUpper),-OffsetMaxLower);
|
||||
//DebugLn(['TCustomSplitter.MoveSplitter Offset=',Offset,' OffsetMaxLower=',OffsetMaxLower,' OffsetMaxUpper=',OffsetMaxUpper]);
|
||||
|
||||
// move splitter
|
||||
if ResizeAnchor in [akLeft,akRight] then begin
|
||||
|
@ -6953,7 +6953,8 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TWinControl.DoDockClientMsg(DragDockObject: TDragDockObject; Position: TPoint): boolean;
|
||||
function TWinControl.DoDockClientMsg(DragDockObject: TDragDockObject;
|
||||
Position: TPoint): boolean;
|
||||
var
|
||||
DestRect: TRect;
|
||||
Form: TCustomForm;
|
||||
|
@ -265,6 +265,7 @@ type
|
||||
procedure RestoreLayout;
|
||||
procedure DisableLayout;
|
||||
procedure EnableLayout;
|
||||
function ControlIsDocked: boolean;
|
||||
function GetControlName(AControl: TControl): string;
|
||||
property Control: TControl read FControl write SetControl;
|
||||
property Manager: TCustomLazDockingManager read FManager write SetManager;
|
||||
@ -651,8 +652,7 @@ begin
|
||||
end;
|
||||
|
||||
// enable Undock button, if Control is docked
|
||||
Dlg.UndockGroupBox.Enabled:=(Control.Parent<>nil)
|
||||
and (Control.Parent.ControlCount>1);
|
||||
Dlg.UndockGroupBox.Enabled:=ControlIsDocked;
|
||||
|
||||
// enable enlarge buttons
|
||||
Dlg.EnlargeLeftSpeedButton.Visible:=
|
||||
@ -743,6 +743,7 @@ begin
|
||||
// control will be hidden -> the layout will change
|
||||
// save the layout for later restore
|
||||
SaveLayout;
|
||||
DebugLn(['TCustomLazControlDocker.ControlVisibleChanging Parent=',DbgSName(Control.Parent)]);
|
||||
end else if ([csDestroying,csDesigning,csLoading]*ComponentState=[]) then begin
|
||||
// the control will become visible -> dock it to restore the last layout
|
||||
RestoreLayout;
|
||||
@ -757,6 +758,19 @@ begin
|
||||
//DebugLn(['TCustomLazControlDocker.ControlVisibleChanged ',DbgSName(Control),' ignore because FLayoutLock=',FLayoutLock]);
|
||||
exit;
|
||||
end;
|
||||
|
||||
if Control.Visible then begin
|
||||
// the control has become visible
|
||||
end else if ([csDesigning,csLoading]*ComponentState=[]) then begin
|
||||
// control was hidden (or destroyed)
|
||||
if ControlIsDocked
|
||||
and (Manager<>nil)
|
||||
and (Manager.Manager<>nil) then begin
|
||||
// auto undock
|
||||
DebugLn(['TCustomLazControlDocker.ControlVisibleChanged auto undock ',DbgSName(Control)]);
|
||||
Manager.Manager.UndockControl(Control,false);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCustomLazControlDocker.CreateFormAndDockWithSplitter(
|
||||
@ -2074,6 +2088,13 @@ begin
|
||||
dec(fLayoutLock);
|
||||
end;
|
||||
|
||||
function TCustomLazControlDocker.ControlIsDocked: boolean;
|
||||
begin
|
||||
Result:=(Control<>nil)
|
||||
and (Control.Parent<>nil)
|
||||
and ((Control.Parent is TLazDockForm) or (Control.Parent is TLazDockPage));
|
||||
end;
|
||||
|
||||
constructor TCustomLazControlDocker.Create(TheOwner: TComponent);
|
||||
begin
|
||||
inherited Create(TheOwner);
|
||||
|
@ -1687,6 +1687,7 @@ begin
|
||||
// DockCtl has no parent
|
||||
// => float DockPages
|
||||
DockPages.ManualFloat(DropCtl.BoundsRect);
|
||||
DockPages.AnchorClient(0);
|
||||
end;
|
||||
// add DockCtl as page to DockPages
|
||||
DockPages.Pages.Add(DropCtl.Caption);
|
||||
@ -1705,6 +1706,7 @@ begin
|
||||
NewPageIndex:=DropCtlPage.PageIndex+1;
|
||||
DockPages.Pages.Insert(NewPageIndex,Control.Caption);
|
||||
NewPage:=DockPages.Page[NewPageIndex];
|
||||
DebugLn(['TCustomAnchoredDockManager.DockControl NewPage=',NewPage.Caption,' Control=',Control.Caption,',',DbgSName(Control)]);
|
||||
NewPage.DisableAlign;
|
||||
try
|
||||
Control.Parent:=NewPage;
|
||||
@ -1820,6 +1822,8 @@ var
|
||||
NewOrigin:=Control.ControlOrigin;
|
||||
OffsetRect(NewBounds,NewOrigin.X,NewOrigin.Y);
|
||||
Control.ManualFloat(NewBounds);
|
||||
if Control.Parent<>nil then
|
||||
Control.AnchorClient(0);
|
||||
end else begin
|
||||
Control.Parent:=nil;
|
||||
end;
|
||||
@ -1834,6 +1838,9 @@ var
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
OldParentPage: TLazDockPage;
|
||||
OldParentForm: TLazDockForm;
|
||||
begin
|
||||
if Control.Parent=nil then begin
|
||||
// already undocked
|
||||
@ -1903,8 +1910,10 @@ begin
|
||||
// check if Control is the only child of a TLazDockPage
|
||||
if (ParentControl.ControlCount=1)
|
||||
and (ParentControl is TLazDockPage) then begin
|
||||
OldParentPage:=TLazDockPage(ParentControl);
|
||||
DoFinallyForParent;
|
||||
DeletePage(TLazDockPage(Control.Parent));
|
||||
DeletePage(OldParentPage);
|
||||
Done:=true;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -1912,8 +1921,10 @@ begin
|
||||
// check if Control is the only child of a TLazDockForm
|
||||
if (ParentControl.ControlCount=1)
|
||||
and (ParentControl is TLazDockForm) then begin
|
||||
OldParentForm:=TLazDockForm(ParentControl);
|
||||
DoFinallyForParent;
|
||||
DeleteDockForm(TLazDockForm(ParentControl));
|
||||
DeleteDockForm(OldParentForm);
|
||||
Done:=true;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user