lcl: Patch for docking: InsertControl (from Hans-Peter Diettrich, mantis #0012909)

git-svn-id: trunk@18094 -
This commit is contained in:
paul 2009-01-04 08:30:53 +00:00
parent 968747c675
commit c92465fa27
4 changed files with 117 additions and 90 deletions

View File

@ -1916,6 +1916,7 @@ type
function GetNextVisibleZone: TDockZone; function GetNextVisibleZone: TDockZone;
function NextVisible: TDockZone; function NextVisible: TDockZone;
function PrevVisible: TDockZone; function PrevVisible: TDockZone;
procedure AddSibling(NewZone: TDockZone; InsertAt: TAlign);
procedure AddAsFirstChild(NewChildZone: TDockZone); procedure AddAsFirstChild(NewChildZone: TDockZone);
procedure AddAsLastChild(NewChildZone: TDockZone); procedure AddAsLastChild(NewChildZone: TDockZone);
procedure ReplaceChild(OldChild, NewChild: TDockZone); procedure ReplaceChild(OldChild, NewChild: TDockZone);
@ -2050,7 +2051,6 @@ type
procedure DeleteZone(Zone: TDockZone); procedure DeleteZone(Zone: TDockZone);
procedure SetDockSite(const AValue: TWinControl); procedure SetDockSite(const AValue: TWinControl);
protected protected
procedure AdjustDockRect(AControl: TControl; var ARect: TRect); virtual;
function HitTest(const MousePos: TPoint; var HTFlag: Integer): TControl; virtual; function HitTest(const MousePos: TPoint; var HTFlag: Integer): TControl; virtual;
procedure PaintDockFrame(ACanvas: TCanvas; AControl: TControl; procedure PaintDockFrame(ACanvas: TCanvas; AControl: TControl;
const ARect: TRect); virtual; const ARect: TRect); virtual;
@ -2061,6 +2061,7 @@ type
destructor Destroy; override; destructor Destroy; override;
procedure BeginUpdate; override; procedure BeginUpdate; override;
procedure EndUpdate; override; procedure EndUpdate; override;
procedure AdjustDockRect(AControl: TControl; var ARect: TRect); virtual;
procedure GetControlBounds(AControl: TControl; procedure GetControlBounds(AControl: TControl;
out ControlBounds: TRect); override; out ControlBounds: TRect); override;
procedure InsertControl(AControl: TControl; InsertAt: TAlign; procedure InsertControl(AControl: TControl; InsertAt: TAlign;

View File

@ -118,14 +118,19 @@ var
begin begin
//determine drop zone //determine drop zone
if DropCtl = nil then if DropCtl = nil then
DropZone := RootZone begin
DropZone := RootZone;
R := DockSite.ClientRect;
end
else else
begin
DropZone := RootZone.FindZone(DropCtl); DropZone := RootZone.FindZone(DropCtl);
if DropZone = nil then
//get the zone extent. DropZone := RootZone;
//r := dzone.FBounds; //todo: doesn't work //get the zone extent.
with DropZone do with DropZone do
R := Rect(Left, Top, Width, Height); R := Rect(Left, Top, Width, Height);
end;
// if there are no zones then use the whole rect // if there are no zones then use the whole rect
// else split drop zone // else split drop zone

View File

@ -290,6 +290,29 @@ begin
inc(FChildCount); inc(FChildCount);
end; end;
procedure TDockZone.AddSibling(NewZone: TDockZone; InsertAt: TAlign);
var
LinkAfter: TDockZone;
begin
case InsertAt of
alLeft, alTop: LinkAfter := FPrevSibling;
alRight, alBottom: LinkAfter := Self;
else
raise Exception.Create('TDockZone.AddSibling: unhandled insertion');
end;
if LinkAfter = nil then
Parent.AddAsFirstChild(NewZone)
else
begin
NewZone.FPrevSibling := LinkAfter;
NewZone.FNextSibling := LinkAfter.NextSibling;
NewZone.FParentZone := Parent;
if LinkAfter.NextSibling <> nil then
LinkAfter.NextSibling.FPrevSibling := NewZone;
LinkAfter.FNextSibling := NewZone;
end;
end;
procedure TDockZone.ReplaceChild(OldChild, NewChild: TDockZone); procedure TDockZone.ReplaceChild(OldChild, NewChild: TDockZone);
begin begin
NewChild.FParentZone := Self; NewChild.FParentZone := Self;

View File

@ -33,7 +33,7 @@ uses
Math, Types, Classes, SysUtils, LCLProc, LCLType, LCLStrConsts, Math, Types, Classes, SysUtils, LCLProc, LCLType, LCLStrConsts,
Graphics, Controls, ExtCtrls, Forms, Menus, Themes, LCLIntf, Graphics, Controls, ExtCtrls, Forms, Menus, Themes, LCLIntf,
LMessages, LResources, typinfo; LMessages, LResources, typinfo;
type type
TLazDockPages = class; TLazDockPages = class;
TLazDockPage = class; TLazDockPage = class;
@ -67,9 +67,9 @@ type
dhiRestore, dhiRestore,
dhiClose dhiClose
); );
TDockHeaderImages = array[TDockHeaderImageKind] of TCustomBitmap; TDockHeaderImages = array[TDockHeaderImageKind] of TCustomBitmap;
{ TLazDockTree } { TLazDockTree }
TLazDockTree = class(TDockTree) TLazDockTree = class(TDockTree)
@ -105,7 +105,7 @@ type
public public
property AutoFreeDockSite: boolean read FAutoFreeDockSite write FAutoFreeDockSite; property AutoFreeDockSite: boolean read FAutoFreeDockSite write FAutoFreeDockSite;
end; end;
TLazDockHeaderPart = TLazDockHeaderPart =
( (
ldhpAll, // total header rect ldhpAll, // total header rect
@ -122,7 +122,7 @@ type
TCustomAnchoredDockManager does not use TLazDockZone and allows arbitrary TCustomAnchoredDockManager does not use TLazDockZone and allows arbitrary
layouts. layouts.
} }
TLazDockForm = class(TCustomForm) TLazDockForm = class(TCustomForm)
private private
FMainControl: TControl; FMainControl: TControl;
@ -153,8 +153,8 @@ type
function GetTitleOrientation(Control: TControl): TDockOrientation; function GetTitleOrientation(Control: TControl): TDockOrientation;
property MainControl: TControl read FMainControl write SetMainControl;// used for the default caption property MainControl: TControl read FMainControl write SetMainControl;// used for the default caption
end; end;
{ TLazDockPage { TLazDockPage
Pretty the same as a TLazDockForm but as page of a TLazDockPages } Pretty the same as a TLazDockForm but as page of a TLazDockPages }
@ -186,18 +186,18 @@ type
write SetActiveNotebookPageComponent; write SetActiveNotebookPageComponent;
property Pages; property Pages;
end; end;
{ TLazDockSplitter } { TLazDockSplitter }
TLazDockSplitter = class(TCustomSplitter) TLazDockSplitter = class(TCustomSplitter)
public public
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
end; end;
TCustomAnchoredDockManager = class; TCustomAnchoredDockManager = class;
{ TLazDockOwnerComponent { TLazDockOwnerComponent
A TComponent owning all automatically created controls of a A TComponent owning all automatically created controls of a
TCustomAnchoredDockManager, like TLazDockForm } TCustomAnchoredDockManager, like TLazDockForm }
@ -208,11 +208,11 @@ type
end; end;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
{ TCustomAnchoredDockManager { TCustomAnchoredDockManager
This class implements an LCL TDockManager via anchoring. This class implements an LCL TDockManager via anchoring.
It implements the docking, undocking, enlarging, shrinking. It implements the docking, undocking, enlarging, shrinking.
The TCustomLazDockingManager component in LDockCtrl uses this The TCustomLazDockingManager component in LDockCtrl uses this
docking manager and extends it by layouts that can be stored/restored. } docking manager and extends it by layouts that can be stored/restored. }
@ -271,8 +271,8 @@ type
// here. // here.
function CreateForm: TLazDockForm; function CreateForm: TLazDockForm;
end; end;
const const
DockAlignOrientations: array[TAlign] of TDockOrientation = DockAlignOrientations: array[TAlign] of TDockOrientation =
( (
@ -322,7 +322,7 @@ type
TDockHeader = class TDockHeader = class
class procedure CreateDockHeaderImages(out Images: TDockHeaderImages); class procedure CreateDockHeaderImages(out Images: TDockHeaderImages);
class procedure DestroyDockHeaderImages(var Images: TDockHeaderImages); class procedure DestroyDockHeaderImages(var Images: TDockHeaderImages);
class function GetRectOfPart(AHeaderRect: TRect; AOrientation: TDockOrientation; APart: TLazDockHeaderPart): TRect; class function GetRectOfPart(AHeaderRect: TRect; AOrientation: TDockOrientation; APart: TLazDockHeaderPart): TRect;
class function FindPart(AHeaderRect: TRect; APoint: TPoint; AOrientation: TDockOrientation): TLazDockHeaderPart; class function FindPart(AHeaderRect: TRect; APoint: TPoint; AOrientation: TDockOrientation): TLazDockHeaderPart;
class procedure Draw(ACanvas: TCanvas; ACaption: String; DockBtnImages: TDockHeaderImages; AOrientation: TDockOrientation; const ARect: TRect; const MousePos: TPoint); class procedure Draw(ACanvas: TCanvas; ACaption: String; DockBtnImages: TDockHeaderImages; AOrientation: TDockOrientation; const ARect: TRect; const MousePos: TPoint);
@ -430,7 +430,7 @@ class procedure TDockHeader.Draw(ACanvas: TCanvas; ACaption: String; DockBtnImag
dy := (ARect.Bottom - ARect.Top - ABitmap.Height) div 2; dy := (ARect.Bottom - ARect.Top - ABitmap.Height) div 2;
ACanvas.Draw(ARect.Left + dx, ARect.Top + dy, ABitmap); ACanvas.Draw(ARect.Left + dx, ARect.Top + dy, ABitmap);
end; end;
var var
BtnRect: TRect; BtnRect: TRect;
DrawRect: TRect; DrawRect: TRect;
@ -445,7 +445,7 @@ begin
ACanvas.Brush.Color := clBtnShadow; ACanvas.Brush.Color := clBtnShadow;
ACanvas.FrameRect(DrawRect); ACanvas.FrameRect(DrawRect);
InflateRect(DrawRect, -1, -1); InflateRect(DrawRect, -1, -1);
IsMouseDown := (GetKeyState(VK_LBUTTON) and $80) <> 0; IsMouseDown := (GetKeyState(VK_LBUTTON) and $80) <> 0;
// draw close button // draw close button
@ -459,7 +459,7 @@ begin
// draw caption // draw caption
DrawRect := GetRectOfPart(ARect, AOrientation, ldhpCaption); DrawRect := GetRectOfPart(ARect, AOrientation, ldhpCaption);
OldMode := SetBkMode(ACanvas.Handle, TRANSPARENT); OldMode := SetBkMode(ACanvas.Handle, TRANSPARENT);
case AOrientation of case AOrientation of
@ -588,11 +588,11 @@ function ControlIsAnchoredIndirectly(StartControl: TControl; Side: TAnchorKind;
DestControl: TControl): boolean; DestControl: TControl): boolean;
{ true if there is an Anchor way from StartControl to DestControl over Side. { true if there is an Anchor way from StartControl to DestControl over Side.
For example: For example:
+-+|+-+ +-+|+-+
|A|||B| |A|||B|
+-+|+-+ +-+|+-+
A is akLeft to B. A is akLeft to B.
B is akRight to A. B is akRight to A.
The splitter is akLeft to B. The splitter is akLeft to B.
@ -602,7 +602,7 @@ function ControlIsAnchoredIndirectly(StartControl: TControl; Side: TAnchorKind;
var var
Checked: array of Boolean; Checked: array of Boolean;
Parent: TWinControl; Parent: TWinControl;
function Check(ControlIndex: integer): boolean; function Check(ControlIndex: integer): boolean;
var var
AControl: TControl; AControl: TControl;
@ -614,7 +614,7 @@ var
Checked[ControlIndex]:=true; Checked[ControlIndex]:=true;
AControl:=Parent.Controls[ControlIndex]; AControl:=Parent.Controls[ControlIndex];
if AControl=DestControl then exit(true); if AControl=DestControl then exit(true);
if (Side in AControl.Anchors) then begin if (Side in AControl.Anchors) then begin
SideControl:=AControl.AnchorSide[Side].Control; SideControl:=AControl.AnchorSide[Side].Control;
if (SideControl<>nil) and Check(Parent.GetControlIndex(SideControl)) then if (SideControl<>nil) and Check(Parent.GetControlIndex(SideControl)) then
@ -631,7 +631,7 @@ var
end; end;
Result:=false; Result:=false;
end; end;
var var
i: Integer; i: Integer;
begin begin
@ -659,19 +659,19 @@ function GetEnclosingControlRect(ControlList: TFPlist; out
ARect: TAnchorControlsRect): boolean; ARect: TAnchorControlsRect): boolean;
{ ARect will be the minimum TAnchorControlsRect around the controls in the list { ARect will be the minimum TAnchorControlsRect around the controls in the list
returns true, if there is such a TAnchorControlsRect. returns true, if there is such a TAnchorControlsRect.
The controls in ARect will either be the Parent or a TLazDockSplitter The controls in ARect will either be the Parent or a TLazDockSplitter
} }
var var
Parent: TWinControl; Parent: TWinControl;
function ControlIsValidAnchor(Control: TControl; Side: TAnchorKind): boolean; function ControlIsValidAnchor(Control: TControl; Side: TAnchorKind): boolean;
var var
i: Integer; i: Integer;
begin begin
Result:=false; Result:=false;
if (Control=ARect[Side]) then exit(true);// this allows Parent at the beginning if (Control=ARect[Side]) then exit(true);// this allows Parent at the beginning
if not (Control is TLazDockSplitter) then if not (Control is TLazDockSplitter) then
exit;// not a splitter exit;// not a splitter
if (TLazDockSplitter(Control).ResizeAnchor in [akLeft,akRight]) if (TLazDockSplitter(Control).ResizeAnchor in [akLeft,akRight])
@ -690,7 +690,7 @@ var
end; end;
Result:=true; Result:=true;
end; end;
var var
TopIndex: Integer; TopIndex: Integer;
TopControl: TControl; TopControl: TControl;
@ -712,7 +712,7 @@ begin
if Parent=nil then exit; if Parent=nil then exit;
for i:=0 to ControlList.Count-1 do for i:=0 to ControlList.Count-1 do
if TControl(ControlList[i]).Parent<>Parent then exit; if TControl(ControlList[i]).Parent<>Parent then exit;
// set the default rect: the Parent // set the default rect: the Parent
Result:=true; Result:=true;
for a:=Low(TAnchorKind) to High(TAnchorKind) do for a:=Low(TAnchorKind) to High(TAnchorKind) do
@ -731,21 +731,21 @@ begin
for TopIndex:=0 to Candidates.Count-1 do begin for TopIndex:=0 to Candidates.Count-1 do begin
TopControl:=TControl(Candidates[TopIndex]); TopControl:=TControl(Candidates[TopIndex]);
if not ControlIsValidAnchor(TopControl,akTop) then continue; if not ControlIsValidAnchor(TopControl,akTop) then continue;
for RightIndex:=0 to Candidates.Count-1 do begin for RightIndex:=0 to Candidates.Count-1 do begin
RightControl:=TControl(Candidates[RightIndex]); RightControl:=TControl(Candidates[RightIndex]);
if (TopControl.AnchorSide[akRight].Control<>RightControl) if (TopControl.AnchorSide[akRight].Control<>RightControl)
and (RightControl.AnchorSide[akTop].Control<>TopControl) then and (RightControl.AnchorSide[akTop].Control<>TopControl) then
continue; // not touching / not a corner continue; // not touching / not a corner
if not ControlIsValidAnchor(RightControl,akRight) then continue; if not ControlIsValidAnchor(RightControl,akRight) then continue;
for BottomIndex:=0 to Candidates.Count-1 do begin for BottomIndex:=0 to Candidates.Count-1 do begin
BottomControl:=TControl(Candidates[BottomIndex]); BottomControl:=TControl(Candidates[BottomIndex]);
if (RightControl.AnchorSide[akBottom].Control<>BottomControl) if (RightControl.AnchorSide[akBottom].Control<>BottomControl)
and (BottomControl.AnchorSide[akRight].Control<>RightControl) then and (BottomControl.AnchorSide[akRight].Control<>RightControl) then
continue; // not touching / not a corner continue; // not touching / not a corner
if not ControlIsValidAnchor(BottomControl,akBottom) then continue; if not ControlIsValidAnchor(BottomControl,akBottom) then continue;
for LeftIndex:=0 to Candidates.Count-1 do begin for LeftIndex:=0 to Candidates.Count-1 do begin
LeftControl:=TControl(Candidates[LeftIndex]); LeftControl:=TControl(Candidates[LeftIndex]);
if (BottomControl.AnchorSide[akLeft].Control<>LeftControl) if (BottomControl.AnchorSide[akLeft].Control<>LeftControl)
@ -765,7 +765,7 @@ begin
end; end;
end; end;
end; end;
Candidates.Free; Candidates.Free;
end; end;
@ -773,7 +773,7 @@ function GetEnclosedControls(const ARect: TAnchorControlsRect): TFPList;
{ return a list of all controls bounded by the anchors in ARect } { return a list of all controls bounded by the anchors in ARect }
var var
Parent: TWinControl; Parent: TWinControl;
procedure Fill(AControl: TControl); procedure Fill(AControl: TControl);
var var
a: TAnchorKind; a: TAnchorKind;
@ -784,10 +784,10 @@ var
if AControl=Parent then exit;// do not add Parent if AControl=Parent then exit;// do not add Parent
for a:=Low(TAnchorKind) to High(TAnchorKind) do for a:=Low(TAnchorKind) to High(TAnchorKind) do
if ARect[a]=AControl then exit;// do not add boundary if ARect[a]=AControl then exit;// do not add boundary
if Result.IndexOf(AControl)>=0 then exit;// already added if Result.IndexOf(AControl)>=0 then exit;// already added
Result.Add(AControl); Result.Add(AControl);
for a:=Low(TAnchorKind) to High(TAnchorKind) do for a:=Low(TAnchorKind) to High(TAnchorKind) do
Fill(AControl.AnchorSide[a].Control); Fill(AControl.AnchorSide[a].Control);
for i:=0 to Parent.ControlCount-1 do begin for i:=0 to Parent.ControlCount-1 do begin
@ -797,7 +797,7 @@ var
Fill(SideControl); Fill(SideControl);
end; end;
end; end;
var var
i: Integer; i: Integer;
AControl: TControl; AControl: TControl;
@ -810,7 +810,7 @@ begin
Parent:=TWinControl(ARect[akLeft]) Parent:=TWinControl(ARect[akLeft])
else else
Parent:=ARect[akLeft].Parent; Parent:=ARect[akLeft].Parent;
// find the left, top most control // find the left, top most control
for i:=0 to Parent.ControlCount-1 do begin for i:=0 to Parent.ControlCount-1 do begin
AControl:=Parent.Controls[i]; AControl:=Parent.Controls[i];
@ -821,7 +821,7 @@ begin
end; end;
end; end;
if Result.Count=0 then exit; if Result.Count=0 then exit;
// use flood fill to find the rest // use flood fill to find the rest
Fill(LeftTopControl); Fill(LeftTopControl);
end; end;
@ -1169,12 +1169,12 @@ procedure TLazDockTree.InsertControl(AControl: TControl; InsertAt: TAlign;
It creates a new TDockZone for AControl and inserts it as a new leaf. It creates a new TDockZone for AControl and inserts it as a new leaf.
It automatically changes the tree, so that the parent of the new TDockZone It automatically changes the tree, so that the parent of the new TDockZone
will have the Orientation for InsertAt. will have the Orientation for InsertAt.
Example 1: Example 1:
A newly created TLazDockTree has only a DockSite (TLazDockForm) and a single A newly created TLazDockTree has only a DockSite (TLazDockForm) and a single
TDockZone - the RootZone, which has as ChildControl the DockSite. TDockZone - the RootZone, which has as ChildControl the DockSite.
Visual: Visual:
+-DockSite--+ +-DockSite--+
| | | |
@ -1241,11 +1241,11 @@ begin
// undock // undock
UndockControlForDocking(AControl); UndockControlForDocking(AControl);
// dock // dock
// create a new zone for AControl // create a new zone for AControl
NewZone := DockZoneClass.Create(Self,AControl) as TLazDockZone; NewZone := DockZoneClass.Create(Self,AControl) as TLazDockZone;
// insert new zone into tree // insert new zone into tree
if (DropZone = RootZone) and (RootZone.FirstChild = nil) then if (DropZone = RootZone) and (RootZone.FirstChild = nil) then
begin begin
@ -1263,7 +1263,7 @@ begin
AControl.BoundsRect := NewBounds; AControl.BoundsRect := NewBounds;
AControl.Parent := DockSite; AControl.Parent := DockSite;
if AControl.Visible then if AControl.Visible then
DockSite.Visible := True; DockSite.Visible := True;
end else end else
@ -1282,7 +1282,7 @@ begin
else else
DropZone := DropZone.GetLastChild; DropZone := DropZone.GetLastChild;
end; end;
// insert a new Parent Zone if needed // insert a new Parent Zone if needed
NeedNewParentZone := True; NeedNewParentZone := True;
if (DropZone.Parent <> nil) then if (DropZone.Parent <> nil) then
@ -1302,7 +1302,7 @@ begin
OldParentZone.ReplaceChild(DropZone, NewParentZone); OldParentZone.ReplaceChild(DropZone, NewParentZone);
NewParentZone.AddAsFirstChild(DropZone); NewParentZone.AddAsFirstChild(DropZone);
end; end;
if DropZone.Parent = nil then if DropZone.Parent = nil then
RaiseGDBException('TLazDockTree.InsertControl Inconsistency DropZone.Parent=nil'); RaiseGDBException('TLazDockTree.InsertControl Inconsistency DropZone.Parent=nil');
// adjust Orientation in tree // adjust Orientation in tree
@ -1318,17 +1318,15 @@ begin
RaiseGDBException('TLazDockTree.InsertControl Inconsistency DropZone.Orientation<>NewOrientation'); RaiseGDBException('TLazDockTree.InsertControl Inconsistency DropZone.Orientation<>NewOrientation');
// insert new node // insert new node
if InsertAt in [alLeft, alTop] then //DoDi: should insert relative to dropzone, not at begin/end of the parent zone
DropZone.Parent.AddAsFirstChild(NewZone) DropZone.AddSibling(NewZone, InsertAt);
else
DropZone.Parent.AddAsLastChild(NewZone);
// add AControl to DockSite // add AControl to DockSite
PrepareControlForResize(AControl); PrepareControlForResize(AControl);
AControl.DockOrientation := NewOrientation; AControl.DockOrientation := NewOrientation;
AControl.Parent := NewZone.GetParentControl; AControl.Parent := NewZone.GetParentControl;
end; end;
// Build dock layout (anchors, splitters, pages) // Build dock layout (anchors, splitters, pages)
if NewZone.Parent <> nil then if NewZone.Parent <> nil then
BuildDockLayout(NewZone.Parent as TLazDockZone) BuildDockLayout(NewZone.Parent as TLazDockZone)
@ -1397,7 +1395,7 @@ procedure TLazDockTree.FindBorderControls(Zone: TLazDockZone; Side: TAnchorKind;
begin begin
if List=nil then List:=TFPList.Create; if List=nil then List:=TFPList.Create;
if Zone=nil then exit; if Zone=nil then exit;
if (Zone.Splitter<>nil) and (Zone.Parent<>nil) if (Zone.Splitter<>nil) and (Zone.Parent<>nil)
and (Zone.Orientation=doVertical) then begin and (Zone.Orientation=doVertical) then begin
// this splitter is leftmost, topmost, bottommost // this splitter is leftmost, topmost, bottommost
@ -1574,7 +1572,7 @@ procedure TLazDockTree.MouseMessage(var Message: TLMessage);
InvalidateRect(DockSite.Handle, @NewMouseState.Rect, False); InvalidateRect(DockSite.Handle, @NewMouseState.Rect, False);
end; end;
end; end;
function FindControlAndPart(MouseMsg: TLMMouse; out ARect: TRect; out APart: TLazDockHeaderPart): TControl; function FindControlAndPart(MouseMsg: TLMMouse; out ARect: TRect; out APart: TLazDockHeaderPart): TControl;
var var
i: integer; i: integer;
@ -1610,7 +1608,7 @@ procedure TLazDockTree.MouseMessage(var Message: TLMessage);
end; end;
Result := nil; Result := nil;
end; end;
var var
ARect: TRect; ARect: TRect;
Part: TLazDockHeaderPart; Part: TLazDockHeaderPart;
@ -1854,19 +1852,19 @@ procedure TCustomAnchoredDockManager.CombineSpiralSplitterPair(Splitter1,
|------ |------
| D | D
} }
procedure MoveAnchorSide(AControl: TControl; Side: TAnchorKind); procedure MoveAnchorSide(AControl: TControl; Side: TAnchorKind);
begin begin
if AControl.AnchorSide[Side].Control=Splitter2 then if AControl.AnchorSide[Side].Control=Splitter2 then
AControl.AnchorSide[Side].Control:=Splitter1; AControl.AnchorSide[Side].Control:=Splitter1;
end; end;
procedure EnlargeSplitter(Side: TAnchorKind); procedure EnlargeSplitter(Side: TAnchorKind);
begin begin
if GetAnchorDepth(Splitter1,Side)>GetAnchorDepth(Splitter2,Side) then if GetAnchorDepth(Splitter1,Side)>GetAnchorDepth(Splitter2,Side) then
Splitter1.AnchorSide[Side].Assign(Splitter2.AnchorSide[Side]); Splitter1.AnchorSide[Side].Assign(Splitter2.AnchorSide[Side]);
end; end;
var var
LeftRightSplitter: boolean; LeftRightSplitter: boolean;
ParentControl: TWinControl; ParentControl: TWinControl;
@ -1900,7 +1898,7 @@ begin
MoveAnchorSide(CurControl,akBottom); MoveAnchorSide(CurControl,akBottom);
end; end;
end; end;
// enlarge Splitter1 // enlarge Splitter1
if LeftRightSplitter then begin if LeftRightSplitter then begin
// enlarge Splitter1 to top and bottom // enlarge Splitter1 to top and bottom
@ -1911,7 +1909,7 @@ begin
EnlargeSplitter(akLeft); EnlargeSplitter(akLeft);
EnlargeSplitter(akRight); EnlargeSplitter(akRight);
end; end;
// delete Splitter2 // delete Splitter2
Splitter2.Free; Splitter2.Free;
finally finally
@ -2100,7 +2098,7 @@ begin
DropCtlAnchor:=MainAlignAnchor[InsertAt]; DropCtlAnchor:=MainAlignAnchor[InsertAt];
ControlAnchor:=OppositeAnchor[DropCtlAnchor]; ControlAnchor:=OppositeAnchor[DropCtlAnchor];
DropCtlTitlePos:=GetPreferredTitlePosition(DropCtl.ClientWidth, DropCtlTitlePos:=GetPreferredTitlePosition(DropCtl.ClientWidth,
DropCtl.ClientHeight); DropCtl.ClientHeight);
@ -2146,7 +2144,7 @@ begin
end; end;
end; end;
if not ParentDisabledAlign then if not ParentDisabledAlign then
begin begin
DropCtl.Parent.DisableAlign; DropCtl.Parent.DisableAlign;
ParentDisabledAlign := True; ParentDisabledAlign := True;
@ -2234,7 +2232,7 @@ begin
// position DropCtl // position DropCtl
DropCtl.AnchorToNeighbour(DropCtlAnchor,0,Splitter); DropCtl.AnchorToNeighbour(DropCtlAnchor,0,Splitter);
// set titles // set titles
UpdateTitlePosition(DropCtl); UpdateTitlePosition(DropCtl);
UpdateTitlePosition(Control); UpdateTitlePosition(Control);
@ -2309,7 +2307,7 @@ end;
Removes a control from a docking form. Removes a control from a docking form.
It breaks all anchors and cleans up. It breaks all anchors and cleans up.
The created gap will be tried to fill up. The created gap will be tried to fill up.
It removes TLazDockSplitter, TLazDockPage and TLazDockPages if they are no It removes TLazDockSplitter, TLazDockPage and TLazDockPages if they are no
longer needed. longer needed.
@ -2342,7 +2340,7 @@ procedure TCustomAnchoredDockManager.UndockControl(Control: TControl; Float: boo
2. Four spiral splitters: 2. Four spiral splitters:
Before: Before:
| |
A | A |
@ -2354,7 +2352,7 @@ procedure TCustomAnchoredDockManager.UndockControl(Control: TControl; Float: boo
| D | D
The left and right splitter will be combined to one. The left and right splitter will be combined to one.
After: After:
| |
A | A |
@ -2369,12 +2367,12 @@ procedure TCustomAnchoredDockManager.UndockControl(Control: TControl; Float: boo
3. No TLazDockSplitter. Control is the only child of a TLazDockPage 3. No TLazDockSplitter. Control is the only child of a TLazDockPage
In this case the page will be deleted. In this case the page will be deleted.
If the TLazDockPages has no childs left, it is recursively undocked. If the TLazDockPages has no childs left, it is recursively undocked.
4. No TLazDockSplitter, Control is the only child of a TLazDockForm. 4. No TLazDockSplitter, Control is the only child of a TLazDockForm.
The TLazDockForm is deleted and the Control is floated. The TLazDockForm is deleted and the Control is floated.
This normally means: A form will simply be placed on the desktop, other This normally means: A form will simply be placed on the desktop, other
controls will be docked into their DockSite. controls will be docked into their DockSite.
5. Otherwise: this control was not docked. 5. Otherwise: this control was not docked.
} }
var var
@ -2416,7 +2414,7 @@ var
ParentControl:=nil; ParentControl:=nil;
DebugLn(['DoFinallyForParent EnableAlign for ',DbgSName(OldParentControl),' Control=',DbgSName(Control),' OldParentControl.ControlCount=',OldParentControl.ControlCount]); DebugLn(['DoFinallyForParent EnableAlign for ',DbgSName(OldParentControl),' Control=',DbgSName(Control),' OldParentControl.ControlCount=',OldParentControl.ControlCount]);
OldParentControl.EnableAlign; OldParentControl.EnableAlign;
// check if the remaining is a TLazDockForm with only one child // check if the remaining is a TLazDockForm with only one child
if (OldParentControl is TLazDockForm) if (OldParentControl is TLazDockForm)
and (OldParentControl.ControlCount=1) then and (OldParentControl.ControlCount=1) then
@ -2435,7 +2433,7 @@ var
end; end;
end; end;
end; end;
var var
OldParentPage: TLazDockPage; OldParentPage: TLazDockPage;
OldParentForm: TLazDockForm; OldParentForm: TLazDockForm;
@ -2445,7 +2443,7 @@ begin
// already undocked // already undocked
RaiseGDBException('TCustomAnchoredDockManager.UndockControl Control.Parent=nil'); RaiseGDBException('TCustomAnchoredDockManager.UndockControl Control.Parent=nil');
end; end;
ParentControl:=Control.Parent; ParentControl:=Control.Parent;
ParentControl.DisableAlign; ParentControl.DisableAlign;
try try
@ -2515,7 +2513,7 @@ begin
Done:=true; Done:=true;
end; end;
end; end;
if not Done then begin if not Done then begin
// check if Control is the only child of a TLazDockForm // check if Control is the only child of a TLazDockForm
if (ParentControl.ControlCount=1) if (ParentControl.ControlCount=1)
@ -2526,11 +2524,11 @@ begin
Done:=true; Done:=true;
end; end;
end; end;
if not Done then begin if not Done then begin
// otherwise: keep // otherwise: keep
end; end;
finally finally
DoFinallyForParent; DoFinallyForParent;
end; end;
@ -2593,14 +2591,14 @@ var
ParentDisabledAlign: Boolean; ParentDisabledAlign: Boolean;
EnlargeSplitter: TLazDockSplitter; EnlargeSplitter: TLazDockSplitter;
RotateSplitter: TLazDockSplitter; RotateSplitter: TLazDockSplitter;
procedure ParentDisableAlign; procedure ParentDisableAlign;
begin begin
if ParentDisabledAlign then exit; if ParentDisabledAlign then exit;
ParentDisabledAlign:=true; ParentDisabledAlign:=true;
Parent.DisableAlign; Parent.DisableAlign;
end; end;
begin begin
Result:=false; Result:=false;
if Control=nil then exit; if Control=nil then exit;
@ -2615,7 +2613,7 @@ begin
if not GetLazDockSplitterOrParent(Control,Side3,Side3Anchor) then exit; if not GetLazDockSplitterOrParent(Control,Side3,Side3Anchor) then exit;
Parent:=Control.Parent; Parent:=Control.Parent;
if (Side2Anchor=Parent) and (Side3Anchor=Parent) then exit; if (Side2Anchor=Parent) and (Side3Anchor=Parent) then exit;
// search controls anchored to the MainSplitter on the other side // search controls anchored to the MainSplitter on the other side
Neighbour:=nil; Neighbour:=nil;
for i:=0 to Parent.ControlCount-1 do begin for i:=0 to Parent.ControlCount-1 do begin
@ -2652,7 +2650,7 @@ begin
if Sibling.Top>Control.Top+Control.Height then continue; if Sibling.Top>Control.Top+Control.Height then continue;
end; end;
end; end;
if Neighbour=nil then if Neighbour=nil then
Neighbour:=Sibling Neighbour:=Sibling
else if Sibling is TLazDockSplitter then begin else if Sibling is TLazDockSplitter then begin
@ -2667,7 +2665,7 @@ begin
if Neighbour=nil then exit; // no neighbour found if Neighbour=nil then exit; // no neighbour found
DebugLn(['TCustomAnchoredDockManager.EnlargeControl Neighbour=',DbgSName(Neighbour)]); DebugLn(['TCustomAnchoredDockManager.EnlargeControl Neighbour=',DbgSName(Neighbour)]);
ParentDisabledAlign:=false; ParentDisabledAlign:=false;
try try
if Neighbour is TLazDockSplitter then begin if Neighbour is TLazDockSplitter then begin
@ -2760,7 +2758,7 @@ begin
end; end;
UpdateTitlePosition(Control); UpdateTitlePosition(Control);
end; end;
end else begin end else begin
// shrink a neighbour control // shrink a neighbour control
DebugLn(['TCustomAnchoredDockManager.EnlargeControl Shrink one control: Neighbour=',DbgSName(Neighbour)]); DebugLn(['TCustomAnchoredDockManager.EnlargeControl Shrink one control: Neighbour=',DbgSName(Neighbour)]);
@ -2777,7 +2775,7 @@ begin
------------------- } ------------------- }
exit; exit;
end; end;
// check if the Neighbour can be shrinked // check if the Neighbour can be shrinked
if NeighbourCanBeShrinked(Control,Neighbour,Side2) then begin if NeighbourCanBeShrinked(Control,Neighbour,Side2) then begin
ShrinkSide:=Side2; ShrinkSide:=Side2;
@ -2787,7 +2785,7 @@ begin
// Neighbour can not be shrinked // Neighbour can not be shrinked
exit; exit;
end; end;
{ EnlargeSplitter { EnlargeSplitter
^ ^