dockmanager example: introduce docking into non-empty root zone

git-svn-id: trunk@24495 -
This commit is contained in:
dodi 2010-04-08 10:15:30 +00:00
parent 8746362f62
commit 812cb0bdad
14 changed files with 230 additions and 118 deletions

View File

@ -14,7 +14,7 @@
<Title Value="EasyDocking"/>
</General>
<VersionInfo>
<ProjectVersion Value=""/>
<StringTable Comments="" CompanyName="" FileDescription="" FileVersion="0.0.0.0" InternalName="" LegalCopyright="" LegalTrademarks="" OriginalFilename="" ProductName="" ProductVersion=""/>
</VersionInfo>
<PublishOptions>
<Version Value="2"/>

View File

@ -238,7 +238,9 @@ begin
if Source.DragTarget = nil then
sb.SimpleText := '<drop nowhere>'
else begin
DropOn := Source.DragTarget;
DropOn := Source.DropOnControl;
if DropOn = nil then
DropOn := Source.DragTarget;
r := Source.DockRect;
s := Format('drop onto %s[%d,%d - %d,%d] %s', [
DropOn.Name, r.Top, r.Left, r.Bottom, r.Right, AlignNames[Source.DropAlign]]);
@ -269,9 +271,11 @@ procedure TEasyDockMain.buDumpClick(Sender: TObject);
var
s: TStringStream;
begin
if not (Docker.DockManager is TEasyTree) then
exit;
s := TStringStream.Create('');
try
Docker.DockManager.SaveToStream(s);
TEasyTree(Docker.DockManager).DumpToStream(s);
DumpBox.Memo1.Text := s.DataString;
finally
s.Free;

View File

@ -25,7 +25,6 @@ implementation
initialization
{$i fTree.lrs}
{$i fTree.lrs}
end.

View File

@ -13,7 +13,7 @@
<UseXPManifest Value="True"/>
</General>
<VersionInfo>
<ProjectVersion Value=""/>
<StringTable Comments="" CompanyName="" FileDescription="" FileVersion="0.0.0.0" InternalName="" LegalCopyright="" LegalTrademarks="" OriginalFilename="" ProductName="" ProductVersion=""/>
</VersionInfo>
<PublishOptions>
<Version Value="2"/>

View File

@ -11,7 +11,7 @@
<UseXPManifest Value="True"/>
</General>
<VersionInfo>
<ProjectVersion Value=""/>
<StringTable Comments="" CompanyName="" FileDescription="" FileVersion="0.0.0.0" InternalName="" LegalCopyright="" LegalTrademarks="" OriginalFilename="" ProductName="" ProductVersion=""/>
</VersionInfo>
<PublishOptions>
<Version Value="2"/>

View File

@ -13,32 +13,6 @@ inherited EditorSite: TEditorSite
OnHide = FormHide
OnResize = FormResize
OnWindowStateChange = FormWindowStateChange
inherited pnlLeft: TPanel
Height = 256
end
inherited splitLeft: TSplitter
Height = 256
end
inherited pnlRight: TPanel
Left = 400
Height = 256
end
inherited pnlBottom: TPanel
Top = 260
Width = 400
end
inherited splitRight: TSplitter
Left = 396
Height = 256
end
inherited StatusBar1: TStatusBar
Top = 261
Width = 400
end
inherited splitBottom: TSplitter
Top = 256
Width = 400
end
object MainMenu1: TMainMenu[7]
left = 240
top = 48

View File

@ -1,40 +1,33 @@
{ This is an automatically generated lazarus resource file }
LazarusResources.Add('TEditorSite','FORMDATA',[
'TPF0'#241#11'TEditorSite'#10'EditorSite'#4'Left'#3'b'#1#6'Height'#3','#1#3'T'
+'op'#3#156#0#5'Width'#3#144#1#7'Caption'#6#10'EditorSite'#12'ClientHeight'#3
+#25#1#11'ClientWidth'#3#144#1#4'Menu'#7#9'MainMenu1'#10'OnActivate'#7#12'For'
+'mActivate'#8'OnCreate'#7#10'FormCreate'#12'OnDeactivate'#7#14'FormDeactivat'
+'e'#6'OnHide'#7#8'FormHide'#8'OnResize'#7#10'FormResize'#19'OnWindowStateCha'
+'nge'#7#21'FormWindowStateChange'#0#241#6'TPanel'#7'pnlLeft'#6'Height'#3#0#1
+#0#0#241#9'TSplitter'#9'splitLeft'#6'Height'#3#0#1#0#0#241#6'TPanel'#8'pnlRi'
+'ght'#4'Left'#3#144#1#6'Height'#3#0#1#0#0#241#6'TPanel'#9'pnlBottom'#3'Top'#3
+#4#1#5'Width'#3#144#1#0#0#241#9'TSplitter'#10'splitRight'#4'Left'#3#140#1#6
+'Height'#3#0#1#0#0#241#10'TStatusBar'#10'StatusBar1'#3'Top'#3#5#1#5'Width'#3
+#144#1#0#0#241#9'TSplitter'#11'splitBottom'#3'Top'#3#0#1#5'Width'#3#144#1#0#0
+#242#2#7#9'TMainMenu'#9'MainMenu1'#4'left'#3#240#0#3'top'#2'0'#0#9'TMenuItem'
+#6'mnFile'#7'Caption'#6#5'&File'#0#9'TMenuItem'#6'mnOpen'#7'Caption'#6#5'&Op'
+'en'#7'OnClick'#7#11'mnOpenClick'#0#0#9'TMenuItem'#9'MenuItem1'#7'Caption'#6
+#1'-'#0#0#9'TMenuItem'#6'mnExit'#7'Caption'#6#5'E&xit'#7'OnClick'#7#11'mnExi'
+'tClick'#0#0#0#9'TMenuItem'#6'mnView'#7'Caption'#6#5'&View'#0#9'TMenuItem'#9
+'MenuItem2'#7'Caption'#6#16'Object Inspector'#7'OnClick'#7#13'ViewMenuClick'
+#0#0#9'TMenuItem'#9'MenuItem3'#7'Caption'#6#8'Messages'#7'OnClick'#7#13'View'
+'MenuClick'#0#0#9'TMenuItem'#9'MenuItem4'#7'Caption'#6#13'Code Explorer'#7'O'
+'nClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuItem5'#7'Caption'#6#9'To'
+'Do List'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuItem6'#7'Cap'
+'tion'#6#13'Debug windows'#0#9'TMenuItem'#9'MenuItem7'#7'Caption'#6#7'Watche'
+'s'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuItem8'#7'Caption'#6
+#11'BreakPoints'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuItem9'
+#7'Caption'#6#15'Local Variables'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenu'
+'Item'#10'MenuItem10'#7'Caption'#6#9'Registers'#7'OnClick'#7#13'ViewMenuClic'
+'k'#0#0#9'TMenuItem'#10'MenuItem11'#7'Caption'#6#10'Call Stack'#7'OnClick'#7
+#13'ViewMenuClick'#0#0#9'TMenuItem'#10'MenuItem12'#7'Caption'#6#9'Assembler'
+#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10'MenuItem13'#7'Caption'#6
+#12'Debug Output'#7'OnClick'#7#13'ViewMenuClick'#0#0#0#0#9'TMenuItem'#10'Men'
+'uItem14'#7'Caption'#6#8'&Windows'#0#9'TMenuItem'#12'mnWindowDump'#7'Caption'
+#6#5'&Dump'#7'OnClick'#7#17'mnWindowDumpClick'#0#0#9'TMenuItem'#10'mnMinimiz'
+'e'#7'Caption'#6#12'Minimize all'#7'OnClick'#7#15'mnMinimizeClick'#0#0#9'TMe'
+'nuItem'#9'mnRestore'#7'Caption'#6#11'Restore all'#7'OnClick'#7#14'mnRestore'
+'Click'#0#0#0#0#242#2#8#11'TOpenDialog'#11'OpenDialog1'#6'Filter'#6#25'*.pas'
+'|*.pas|All Files|*.*'#4'left'#3'5'#1#3'top'#2'0'#0#0#0
+'nge'#7#21'FormWindowStateChange'#0#242#2#7#9'TMainMenu'#9'MainMenu1'#4'left'
+#3#240#0#3'top'#2'0'#0#9'TMenuItem'#6'mnFile'#7'Caption'#6#5'&File'#0#9'TMen'
+'uItem'#6'mnOpen'#7'Caption'#6#5'&Open'#7'OnClick'#7#11'mnOpenClick'#0#0#9'T'
+'MenuItem'#9'MenuItem1'#7'Caption'#6#1'-'#0#0#9'TMenuItem'#6'mnExit'#7'Capti'
+'on'#6#5'E&xit'#7'OnClick'#7#11'mnExitClick'#0#0#0#9'TMenuItem'#6'mnView'#7
+'Caption'#6#5'&View'#0#9'TMenuItem'#9'MenuItem2'#7'Caption'#6#16'Object Insp'
+'ector'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuItem3'#7'Capti'
+'on'#6#8'Messages'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuIte'
+'m4'#7'Caption'#6#13'Code Explorer'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMe'
+'nuItem'#9'MenuItem5'#7'Caption'#6#9'ToDo List'#7'OnClick'#7#13'ViewMenuClic'
+'k'#0#0#9'TMenuItem'#9'MenuItem6'#7'Caption'#6#13'Debug windows'#0#9'TMenuIt'
+'em'#9'MenuItem7'#7'Caption'#6#7'Watches'#7'OnClick'#7#13'ViewMenuClick'#0#0
+#9'TMenuItem'#9'MenuItem8'#7'Caption'#6#11'BreakPoints'#7'OnClick'#7#13'View'
+'MenuClick'#0#0#9'TMenuItem'#9'MenuItem9'#7'Caption'#6#15'Local Variables'#7
+'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10'MenuItem10'#7'Caption'#6#9
+'Registers'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10'MenuItem11'#7
+'Caption'#6#10'Call Stack'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10
+'MenuItem12'#7'Caption'#6#9'Assembler'#7'OnClick'#7#13'ViewMenuClick'#0#0#9
+'TMenuItem'#10'MenuItem13'#7'Caption'#6#12'Debug Output'#7'OnClick'#7#13'Vie'
+'wMenuClick'#0#0#0#0#9'TMenuItem'#10'MenuItem14'#7'Caption'#6#8'&Windows'#0#9
+'TMenuItem'#12'mnWindowDump'#7'Caption'#6#5'&Dump'#7'OnClick'#7#17'mnWindowD'
+'umpClick'#0#0#9'TMenuItem'#10'mnMinimize'#7'Caption'#6#12'Minimize all'#7'O'
+'nClick'#7#15'mnMinimizeClick'#0#0#9'TMenuItem'#9'mnRestore'#7'Caption'#6#11
+'Restore all'#7'OnClick'#7#14'mnRestoreClick'#0#0#0#0#242#2#8#11'TOpenDialog'
+#11'OpenDialog1'#6'Filter'#6#25'*.pas|*.pas|All Files|*.*'#4'left'#3'5'#1#3
+'top'#2'0'#0#0#0
]);

View File

@ -41,7 +41,8 @@ uses
fEditForm;
type
TEditorSite = class(TDockingSite)
//TEditorSite = class(TDockingSite)
TEditorSite = class(TForm)
MenuItem10: TMenuItem;
MenuItem11: TMenuItem;
MenuItem12: TMenuItem;

View File

@ -8,11 +8,11 @@
<MainUnit Value="0"/>
<AutoCreateForms Value="False"/>
<TargetFileExt Value=".exe"/>
<Icon Value="0"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
</General>
<VersionInfo>
<ProjectVersion Value=""/>
<StringTable Comments="" CompanyName="" FileDescription="" FileVersion="0.0.0.0" InternalName="" LegalCopyright="" LegalTrademarks="" OriginalFilename="" ProductName="" ProductVersion=""/>
</VersionInfo>
<PublishOptions>
<Version Value="2"/>

View File

@ -18,8 +18,6 @@ object ViewWindow: TViewWindow
Width = 142
AutoSize = False
Caption = 'Label1'
DragKind = dkDock
DragMode = dmAutomatic
ParentColor = False
end
object Image1: TImage

View File

@ -1,22 +1,24 @@
{ This is an automatically generated lazarus resource file }
LazarusResources.Add('TViewWindow','FORMDATA',[
'TPF0'#11'TViewWindow'#10'ViewWindow'#4'Left'#3'q'#1#6'Height'#3','#1#3'Top'#3
+'q'#1#5'Width'#3#144#1#7'Caption'#6#10'ViewWindow'#12'ClientHeight'#3','#1#11
+'ClientWidth'#3#144#1#8'DragKind'#7#6'dkDock'#8'DragMode'#7#11'dmAutomatic'#9
+'OnEndDock'#7#11'FormEndDock'#10'LCLVersion'#6#6'0.9.29'#7'Visible'#9#0#6'TL'
+'abel'#6'Label1'#4'Left'#2#16#6'Height'#2#14#3'Top'#2#8#5'Width'#3#142#0#8'A'
+'utoSize'#8#7'Caption'#6#6'Label1'#8'DragKind'#7#6'dkDock'#8'DragMode'#7#11
+'dmAutomatic'#11'ParentColor'#8#0#0#6'TImage'#6'Image1'#4'Left'#3#128#1#6'He'
+'ight'#2#16#3'Top'#2#0#5'Width'#2#16#7'Anchors'#11#5'akTop'#7'akRight'#0#8'A'
+'utoSize'#9#11'OnMouseMove'#7#15'Image1MouseMove'#12'Picture.Data'#10'H'#1#0
+#0#5'TIcon>'#1#0#0#0#0#1#0#1#0#16#16#16#0#0#0#0#0'('#1#0#0#22#0#0#0'('#0#0#0
+#16#0#0#0' '#0#0#0#1#0#4#0#0#0#0#0#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+#0#0#0#0#0#0#128#0#0#128#0#0#0#128#128#0#128#0#0#0#128#0#128#0#128#128#0#0
+#128#128#128#0#192#192#192#0#0#0#255#0#0#255#0#0#0#255#255#0#255#0#0#0#255#0
+#255#0#255#255#0#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+'utoSize'#8#7'Caption'#6#6'Label1'#11'ParentColor'#8#0#0#6'TImage'#6'Image1'
+#4'Left'#3#128#1#6'Height'#2#16#3'Top'#2#0#5'Width'#2#16#7'Anchors'#11#5'akT'
+'op'#7'akRight'#0#8'AutoSize'#9#11'OnMouseMove'#7#15'Image1MouseMove'#12'Pic'
+'ture.Data'#10'H'#1#0#0#5'TIcon>'#1#0#0#0#0#1#0#1#0#16#16#16#0#0#0#0#0'('#1#0
+#0#22#0#0#0'('#0#0#0#16#0#0#0' '#0#0#0#1#0#4#0#0#0#0#0#192#0#0#0#0#0#0#0#0#0
+#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#0#0#128#0#0#0#128#128#0#128#0#0#0#128#0
+#128#0#128#128#0#0#128#128#128#0#192#192#192#0#0#0#255#0#0#255#0#0#0#255#255
+#0#255#0#0#0#255#0#255#0#255#255#0#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+#0#153#0#0#0#0#0#0#153#153#153#0#0#0#0#0#153#153#153#0#0#0#0#9#153#153#153
+#144#0#0#0#9#153#153#153#144#0#0#0#0#153#153#153#0#0#0#0#0#153#153#153#0#0#0
+#0#0#0#153#0#0#0#0#0#0#0#0#0#0#127#255#0#0#191#255#0#0#223#255#0#0#239#255#0
+#0#247#255#0#0#251#255#0#0#253#207#0#0#254#3#0#0#254#1#0#0#254#1#0#0#252#0#0
+#0#252#0#0#0#254#1#0#0#254#1#0#0#255#3#0#0#255#207#0#0#0#0#0
+#0#0#0#0#0#0#0#0#0#0#153#0#0#0#0#0#0#153#153#153#0#0#0#0#0#153#153#153#0#0#0
+#0#9#153#153#153#144#0#0#0#9#153#153#153#144#0#0#0#0#153#153#153#0#0#0#0#0
+#153#153#153#0#0#0#0#0#0#153#0#0#0#0#0#0#0#0#0#0#127#255#0#0#191#255#0#0#223
+#255#0#0#239#255#0#0#247#255#0#0#251#255#0#0#253#207#0#0#254#3#0#0#254#1#0#0
+#254#1#0#0#252#0#0#0#252#0#0#0#254#1#0#0#254#1#0#0#255#3#0#0#255#207#0#0#0#0
+#0
]);

View File

@ -47,6 +47,7 @@
<UnitName Value="uMakeSite"/>
</Item7>
</Files>
<LazDoc Paths="..\docs\"/>
<Type Value="RunAndDesignTime"/>
<RequiredPkgs Count="2">
<Item1>

View File

@ -53,6 +53,7 @@ LCL TODO:
{$mode objfpc}{$H+}
{$DEFINE RootDock} //allow docking into the root zone?
//{$DEFINE newSplitter} //exclude splitter from remaining zone
{.$DEFINE handle_existing} //dock controls existing in the dock site?
{.$DEFINE splitter_color} //use colored splitter, for debugging?
@ -105,14 +106,12 @@ type
TEasyDockHeader = class
public
//HeaderSize: integer;
//state last drawn
MouseZone: TEasyZone;
MouseDown: boolean;
MousePart: TEasyZonePart;
PartRect: TRect;
public
//Style: TEasyHeaderStyle;
constructor Create;
function GetRectOfPart(ARect: TRect; AOrientation: TDockOrientation; APart: TEasyZonePart; HasSplitter: boolean; AStyle: TEasyHeaderStyle): TRect; virtual;
function FindPart(AZone: TEasyZone; MousePos: TPoint; fButtonDown: boolean): TEasyZonePart;
@ -186,6 +185,7 @@ type
constructor Create(ADockSite: TWinControl); override;
class function DetectAlign(ZoneRect: TRect; MousePos: TPoint): TAlign;
function GetDockEdge(ADockObject: TDragDockObject): boolean; override;
procedure PositionDockRect(ADockObject: TDragDockObject); override;
procedure PositionDockRect(Client, DropCtl: TControl; DropAlign: TAlign;
var DockRect: TRect); override;
procedure SetReplacingControl(Control: TControl); override; //unused
@ -575,10 +575,17 @@ begin
end;
end;
const
OrthoOrientation: array[TDockOrientation] of TDockOrientation = (
//doNoOrient, doHorizontal, doVertical, doPages
doNoOrient, doVertical, doHorizontal, doPages
);
procedure TEasyTree.InsertControl(Control: TControl; InsertAt: TAlign;
DropCtl: TControl);
var
DropZone, OldZone, NewZone, OldParent, NewParent: TEasyZone;
OldOrientation, NewOrientation: TDockOrientation;
r: TRect;
NoteBook: TCustomDockSite;
(* special cases:
@ -633,17 +640,18 @@ begin
exit; //nothing changed
end;
if Control.Name = '' then //name it - for header caption
Control.Name := CreateUniqueComponentName(Control.ClassName, Control.Owner);
if DropCtl = nil then begin
DropCtl := FDockSite; //the dock site
DropZone := FTopZone.FirstChild;
//top level docking!
//DropCtl := FDockSite; //the dock site
DropZone := FTopZone; // FTopZone.FirstChild;
end else begin
DropZone := FindControlZone(FTopZone, DropCtl);
if DropZone = nil then exit; //not here!?
end;
if Control.Name = '' then //name it - for header caption
Control.Name := CreateUniqueComponentName(Control.ClassName, Control.Owner);
(* alCustom means: drop into notebook.
Valid only when dropped onto an existing control, not into empty dock site.
Create notebook, if required (put both controls into new notebook).
@ -695,10 +703,13 @@ begin
NewZone := TEasyZone.Create(self);
NewZone.ChildControl := Control as TControl;
Control.Align := alNone;
if Control is TCustomForm then
TCustomForm(Control).BorderStyle := bsNone;
//special case: in root zone (empty dock site)
if FTopZone.FirstChild = nil then begin
//insert first, without orientation
FTopZone.InsertAfter(nil, NewZone);
NewZone.SetBounds(FDockSite.ClientRect);
end else begin
@ -708,43 +719,78 @@ begin
r := DropZone.GetBounds; //for later adjustment
//get requested orientation, adjust align
case InsertAt of
alTop, alBottom: Control.DockOrientation := doVertical;
alLeft, alRight: Control.DockOrientation := doHorizontal;
alTop, alBottom: NewOrientation := doVertical;
alLeft, alRight: NewOrientation := doHorizontal;
else //unhandled or unspecific
if DropCtl.DockOrientation = doNoOrient then
DropCtl.DockOrientation := doHorizontal; //assume
Control.DockOrientation := DropCtl.DockOrientation;
{ TODO : DropCtl=nil - if docked into root zone }
if (DropCtl = nil) or (DropCtl.DockOrientation = doNoOrient) then begin
NewOrientation := DropZone.Orientation;
end else
NewOrientation := DropCtl.DockOrientation;
if NewOrientation = doNoOrient then
NewOrientation := doHorizontal; //assume something
//fix alignment
if Control.DockOrientation = doVertical then
if NewOrientation = doVertical then
InsertAt := alBottom
else
InsertAt := alRight;
end;
Control.DockOrientation := NewOrientation;
{
//check topzone now must have an orientation
if FTopZone.Orientation = doNoOrient then begin
FTopZone.Orientation := NewOrientation;
FTopZone.FirstChild.ChildControl.DockOrientation := NewOrientation;
end;
}
(* Now Control.DockOrientation is the insert orientation,
DropCtl.DockOrientation is the zone orientation,
InsertAt is one of alLeft/Right/Top/Bottom
*)
//check orientation - control orientation cannot be doNone!
OldParent := DropZone.Parent;
(* One special case remains: top zone without orientation
*)
if (OldParent.Orientation = doNoOrient) then begin
assert(OldParent = FTopZone, '???');
FTopZone.Orientation := Control.DockOrientation; //easy
OldParent := DropZone.Parent; //nil if docked into root zone!
if OldParent = nil then begin
//dock into rootzone - may have no orientation
OldOrientation := FTopZone.Orientation; // OrthoOrientation[FTopZone.Orientation];
end else
OldOrientation := OldParent.Orientation;;
if (OldOrientation = doNoOrient) then begin
//second insert into root zone - fix zone and control orientation!
//assert(OldParent = FTopZone, '???');
OldOrientation := NewOrientation; // Control.DockOrientation; //easy
FTopZone.Orientation := NewOrientation;
FTopZone.FirstChild.ChildControl.DockOrientation := NewOrientation;
end;
//iso or orthogonal insert?
if (OldParent.Orientation <> Control.DockOrientation) then begin
if (OldOrientation <> NewOrientation) then begin
//need intermediate zone
NewParent := TEasyZone.Create(self);
NewParent.Orientation := Control.DockOrientation;
NewParent.Orientation := NewOrientation;
NewParent.BR := r.BottomRight;
OldParent.ReplaceChild(DropZone, NewParent); //unlink DropZone
if OldParent <> nil then
OldParent.ReplaceChild(DropZone, NewParent) //unlink DropZone
else begin
//DropZone is FTopZone
FTopZone := NewParent;
{ TODO : what more is required??? }
end;
//orthogonal orientation
NewParent.InsertAfter(nil, DropZone);
end;
//set control orientation
//set control orientation - !rootzone?
if DropZone = FTopZone then begin
//dropzone must have a parent
DropZone := DropZone.FirstChild;
case InsertAt of
//alLeft, alTop:
alBottom, alRight:
while DropZone.NextSibling <> nil do
DropZone := DropZone.NextSibling;
end;
end;
DropZone.AddSibling(NewZone, InsertAt);
//if FTopZone.Orientation = doNoOrient then FTopZone.Orientation := Control.DockOrientation;
//clear eventually moved zone, when redocking within this site
if OldZone <> nil then begin
RemoveZone(OldZone); //must NOT modify moved control!
@ -762,6 +808,9 @@ var
begin
(* New DockManager interface, called instead of the old version.
Determine exact target (zone) and DropAlign.
For top-level docking: check mouse IN site!
Signal results:
Prevent docking by setting DropOnControl=Control (prevent changes when dropped).
DragTarget=nil means: become floating.
@ -770,6 +819,7 @@ Signal results:
*)
{ TODO -cdocking : why is this method not called for a docksite with 1 client?
If exactly the client is moved over it?
-> by design of GetDockTarget in DockPerformer!
}
//debug only
DockObj := ADockObject;
@ -777,9 +827,13 @@ Signal results:
//determine the zone containing the DragTargetPos
with ADockObject do begin
//mouse position within dock site
DragTargetPos := DragTarget.ScreenToClient(DragPos);
//DragTargetPos := DragTarget.ScreenToClient(DragPos);
//find zone, handle empty site for elastic panels
if DockSite.DockClientCount = 0 then
if (DockSite.DockClientCount = 0)
{$IFDEF RootDock}
or (not PtInRect(DockRect, DragPos))
{$ENDIF}
then
zone := FTopZone
else
zone := ZoneFromPoint(DragTargetPos);
@ -788,8 +842,12 @@ Signal results:
DropAlign := alNone; //prevent drop (below)
end else begin
ADockRect := zone.GetBounds; //include header
DropOnControl := zone.ChildControl;
DropAlign := DetectAlign(ADockRect, DragTargetPos);
DropOnControl := zone.ChildControl; //correct hit in header, not in control
if DockSite.DockClientCount = 0 then
DropAlign := alClient //always span empty site
else
DropAlign := DetectAlign(ADockRect, DragTargetPos);
{$IFnDEF RootDock}
if DropOnControl = nil then begin
{$IFDEF singleTab}
if SingleTab and (DropAlign = alCustom) then begin
@ -798,6 +856,9 @@ Signal results:
{$ENDIF}
DropAlign := alClient; //first element in entire site
end; //else //determine the alignment within the zone.
{$ELSE}
//allow for top-level docking
{$ENDIF}
//to screen coords
ADockRect.TopLeft := FDockSite.ClientToScreen(ADockRect.TopLeft);
ADockRect.BottomRight := FDockSite.ClientToScreen(ADockRect.BottomRight);
@ -1336,7 +1397,7 @@ begin
affected := p;
until zone.FirstChild <> nil;
(* cases:
zone without parent (top) - exit
zone without parent (top) - check orientation, exit
zone with 0 children - excluded before
zone with 1 child (ch),
child is leaf -> looses orientation, move up
@ -1350,7 +1411,7 @@ begin
//more than 1 child - check next level
end else if ch.FirstChild = nil then begin
//contains control, move up
ch.ChildControl.DockOrientation := zone.Parent.Orientation;
ch.ChildControl.DockOrientation := p.Orientation;
p.ReplaceChild(zone, ch); //move control up
zone.Free;
affected := p;
@ -1371,7 +1432,37 @@ begin
zone.PositionControl;
zone := Zone.NextSibling;
end;
{
//root zone may loose orientation!
if affected = FTopZone then begin
if affected.FirstChild.NextSibling = nil then begin
FTopZone.Orientation := doNoOrient;
FTopZone.FirstChild.ChildControl.DockOrientation := doNoOrient; <--- non-leaf!?
end;
end;
}
end;
{$IFDEF new}
while FTopZone.FirstChild <> nil do begin
Zone := FTopZone.FirstChild;
if Zone.NextSibling <> nil then
break;
//move zone up
FTopZone.FFirstChild := nil;
zone.Parent := nil;
FTopZone.Free;
FTopZone := zone;
end;
{$ELSE}
{$ENDIF}
if FTopZone.FirstChild = nil then
FTopZone.Orientation := doNoOrient
else if FTopZone.FirstChild.NextSibling = nil then begin
FTopZone.Orientation := doNoOrient;
FTopZone.FirstChild.ChildControl.DockOrientation := doNoOrient;
//bug: not leaf???
end;
//update zone, here simply the whole dock site
FSplitter.Hide;
DockSite.Invalidate;
@ -1557,6 +1648,7 @@ begin
end;
//parent orientation? (if in rootzone)
//if parent.Orientation = doNoOrient then
if Parent <> nil then
Parent.Orientation := NewOrientation;
if ChildControl <> nil then
ChildControl.DockOrientation := NewOrientation;
@ -1761,7 +1853,7 @@ const
alLeft, alLeft, alTop, alTop, alRight, alBottom, alBottom, alLeft, alLeft
);
begin
(* Determine alignment from the location of the mouse within ZoneRect.
(* Determine alignment from the position of the mouse within ZoneRect.
ZoneRect in screen TLBR coordinates, MousePos in screen coordinates.
*)
//center and extent of dock zone
@ -1779,8 +1871,8 @@ begin
//zone := zInnermost;
dir := alCustom; //pages
end else begin
phi := arctan2(dy, dx);
zphi := trunc(radtodeg(phi)) div 45;
phi := arctan2(dy, dx); //zero at East (right), increasing clockwise
zphi := trunc(radtodeg(phi)) div 45; //both EN and ES are zero
dir := cDir[zphi];
end;
end else
@ -1806,7 +1898,11 @@ begin
Usage: Only to prevent calls to the target control, in case of extended
InfluenceRect.
*)
//test
exit(false);
if false then Result:=inherited GetDockEdge(ADockObject);
{$IFDEF old}
//ADockObject.DockRect
Result := DockSite.DockClientCount = 0; //do nothing if docked clients exist!
if Result then begin
@ -1826,7 +1922,16 @@ begin
ADockObject.DockRect := r;
Result := CanDock;
end;
//Result := True;
{$ELSE}
DebugLn('DropOnControl ', DbgS(ADockObject.DropOnControl));
ADockObject.DropAlign := DetectAlign(ADockObject.DockRect, ADockObject.DragPos);
Result := True;
DebugLn('dockedge x(%d-%d) y(%d-%d) %s', [
ADockObject.DockRect.Left, ADockObject.DockRect.Right,
ADockObject.DockRect.Top, ADockObject.DockRect.Bottom,
AlignNames[ADockObject.DropAlign]
]);
{$ENDIF}
end;
procedure TEasyDockManager.PositionDockRect(Client, DropCtl: TControl;
@ -1836,10 +1941,16 @@ var
begin
(* DockRect is initialized to the screen rect of the dock site by TControl,
or to the zone rect by TEasyTree.
DropCtl=Nil means: dock into the root zone.
*)
//if False then inherited PositionDockRect(Client, DropCtl, DropAlign, DockRect);
{$IFDEF old}
if (DropCtl = nil) {$IFDEF singleTab} and not SingleTab {$ENDIF} then
//if (DropCtl = nil) then
exit; //entire dock site
{$ELSE}
{$ENDIF}
case DropAlign of
//alClient: as is
@ -1859,6 +1970,33 @@ begin
end;
end;
procedure TEasyDockManager.PositionDockRect(ADockObject: TDragDockObject);
var
r: TRect;
begin
(* Something is wrong here?
ADockObject:
DockRect is the site rect, to be replaced by the target control/zone rect.
*)
//test
exit;
if false then inherited PositionDockRect(ADockObject);
with ADockObject do begin;
//check target
if DropOnControl <> nil then begin
//init control rect
r.TopLeft := DropOnControl.ClientOrigin;
r.Bottom := r.Top + DropOnControl.Height;
r.Right := r.Left + DropOnControl.Width;
end else begin
r := DockRect;
end;
DetectAlign(r, DragPos);
end;
end;
procedure TEasyDockManager.SetReplacingControl(Control: TControl);
begin
//nop

View File

@ -31,9 +31,11 @@ var
ImageKind: TDockHeaderImageKind;
begin
//called from unit finalization only!
// this code can result in crashes, due to missing handles
// this code can result in crashes, due to missing handles!
{
for ImageKind := Low(TDockHeaderImageKind) to High(TDockHeaderImageKind) do
FreeAndNil(DockBtnImages[ImageKind]);
}
end;