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:
mattias 2008-01-15 19:31:02 +00:00
parent 84a32a76be
commit f3efce1701
10 changed files with 173 additions and 40 deletions

View File

@ -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

View File

@ -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
]);

View File

@ -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;

View File

@ -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>

View File

@ -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

View File

@ -3390,7 +3390,7 @@ begin
//debugln('TControl.Dock A ',DbgSName(Self));
DoDock(NewDockSite,ARect);
if FHostDockSite<>NewDockSite then
begin
// HostDockSite has changed -> commit

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;