fixed compilation under fpc 2.1.1

git-svn-id: trunk@9694 -
This commit is contained in:
mattias 2006-07-31 07:38:52 +00:00
parent 85de8ce1f8
commit 43b02b83ea
3 changed files with 265 additions and 140 deletions

View File

@ -92,8 +92,6 @@ begin
ControlDocker1.Manager:=DockingManager; ControlDocker1.Manager:=DockingManager;
DockingManager.WriteDebugReport; DockingManager.WriteDebugReport;
DockingManager.CreateLayout(ControlDocker1.DockerName,Self,true);
Halt;
Form2:=CreateNewForm; Form2:=CreateNewForm;
Form3:=CreateNewForm; Form3:=CreateNewForm;
@ -104,9 +102,8 @@ begin
DockingManager.Manager.InsertControl(Form3,alBottom,Self); DockingManager.Manager.InsertControl(Form3,alBottom,Self);
end; end;
DockingManager.WriteDebugReport; //DockingManager.WriteDebugReport;
//ControlDocker1.GetLayoutFromControl;
ControlDocker1.GetLayoutFromControl;
end; end;
procedure TMainForm.FormDestroy(Sender: TObject); procedure TMainForm.FormDestroy(Sender: TObject);

View File

@ -20,11 +20,10 @@ unit newfield;
interface interface
uses uses
Classes, SysUtils, DBConst, LCLIntf, Graphics, Controls, Forms, Dialogs, Classes, Math, SysUtils, DBConst, LCLIntf, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, Buttons, DB, LResources, ComponentEditors, ExtCtrls, StdCtrls, Buttons, DB, LResources, ComponentEditors,
PropEdits, TypInfo; PropEdits, TypInfo;
type type
{ TNewFieldFrm } { TNewFieldFrm }

View File

@ -416,11 +416,12 @@ begin
exit; exit;
end; end;
DebugLn(['TCustomLazControlDocker.ControlVisibleChanging Sender=',DbgSName(Sender)]); DebugLn(['TCustomLazControlDocker.ControlVisibleChanging Sender=',DbgSName(Sender)]);
DumpStack;
if Control.Visible then begin if Control.Visible then begin
// control will be hidden -> the layout will change // control will be hidden -> the layout will change
// save the layout for later restore // save the layout for later restore
SaveLayout; SaveLayout;
end else begin end else if ([csDestroying,csDesigning,csLoading]*ComponentState=[]) then begin
// the control will become visible -> dock it to restore the last layout // the control will become visible -> dock it to restore the last layout
RestoreLayout; RestoreLayout;
end; end;
@ -429,6 +430,7 @@ end;
procedure TCustomLazControlDocker.ControlVisibleChanged(Sender: TObject); procedure TCustomLazControlDocker.ControlVisibleChanged(Sender: TObject);
begin begin
DebugLn(['TCustomLazControlDocker.ControlVisibleChanged Sender=',DbgSName(Sender)]); DebugLn(['TCustomLazControlDocker.ControlVisibleChanged Sender=',DbgSName(Sender)]);
DumpStack;
end; end;
function TCustomLazControlDocker.GetControlName(AControl: TControl): string; function TCustomLazControlDocker.GetControlName(AControl: TControl): string;
@ -768,60 +770,95 @@ procedure TCustomLazControlDocker.RestoreLayout;
|+---+#+-----------------+| |+---+#+-----------------+|
+-------------------------+ +-------------------------+
} }
type
TSiblingDistance = (
sdUnknown,
sdThreeSides, // sibling shares 3 sides
sdOneSide, // sibling shares 1 side
sdSplitterThreeSides,// splitter, then sibling shares 3 sides
sdSplitterOneSide // splitter, then sibling shares 1 side
);
var var
Layout: TLazDockerConfig; Layout: TLazDockConfigNode;
SelfNode: TLazDockConfigNode; SelfNode: TLazDockConfigNode;
procedure RaiseLayoutInconsistency(Node: TLazDockConfigNode); function FindNode(const ANodeName: string): TLazDockConfigNode;
begin begin
raise Exception.Create('TCustomLazControlDocker.RestoreLayout' if ANodeName='' then
+' DockerName="'+DockerName+'"' Result:=nil
+' Control='+DbgSName(Control)
+' Node='+Node.Name);
end;
procedure FindSibling(Node: TLazDockConfigNode; Side: TAnchorKind;
out Sibling: TControl; out SiblingNode: TLazDockConfigNode;
out Distance: TSiblingDistance);
// find the nearest visible sibling control at Side
var
SiblingName: string;
begin
Sibling:=nil;
SiblingNode:=nil;
Distance:=sdUnknown;
if Node=nil then exit;
SiblingName:=Node.Sides[Side];
if SiblingName<>'' then begin
SiblingNode:=Layout.Root.FindByName(SiblingName,true);
if SiblingNode=nil then
RaiseLayoutInconsistency(Node);
case SiblingNode.TheType of
ldcntSplitterLeftRight,ldcntSplitterUpDown:
begin
FindSibling(SiblingNode,Side,Sibling,SiblingNode,Distance);
if Distance=sdOneSide then
Distance:=sdSplitterOneSide;
if Distance=sdThreeSides then
Distance:=sdSplitterThreeSides;
if Distance=sdSplitterThreeSides then begin
end;
exit;
end;
else else
exit; Result:=Layout.FindByName(ANodeName,true,true);
end; end;
function FindNodeUsingSplitter(Splitter: TLazDockConfigNode;
SiblingSide: TAnchorKind; NilIfAmbiguous: boolean): TLazDockConfigNode;
var
i: Integer;
ParentNode: TLazDockConfigNode;
Child: TLazDockConfigNode;
begin
Result:=nil;
ParentNode:=Splitter.Parent;
for i:=0 to ParentNode.ChildCount-1 do begin
Child:=ParentNode.Childs[i];
if CompareText(Child.Sides[SiblingSide],Splitter.Name)=0 then begin
if Result=nil then
Result:=Child
else if NilIfAmbiguous then
exit(nil);
end;
end;
end;
function SplitterIsOnlyUsedByNodeAtSide(Splitter, Node: TLazDockConfigNode;
SiblingSide: TAnchorKind): boolean;
{ check if one side of the Splitter is only used by Node.
For example: If only Node.Sides[SiblingSide]=Splitter.Name
---------+
--+#+---+|
B |#| A ||
--+#+---+|
---------+}
begin
Result:=FindNodeUsingSplitter(Splitter,SiblingSide,true)<>nil;
end;
function DockWithOwnSplitter(Side: TAnchorKind): boolean;
{ Add a splitter to Side and dock to it. For example:
--------+ -----------+
---+| ----+#+---+|
B | -> B |#| A ||
---+| ----+#+---+|
--------+ -----------+
If B has no parent, a TLazDockForm is created.
To get space for A, either B is shrinked and/or the parent of B is enlarged
(including the grand parents of B).
}
begin
// TODO // TODO
Result:=false;
end; end;
function DockWithSpiralSpltter: boolean;
begin
// TODO
Result:=false;
end;
function SplitterDocking: boolean;
var
a: TAnchorKind;
SplitterCount: Integer;
SideNode: TLazDockConfigNode;
begin
SplitterCount:=0;
for a:=Low(TAnchorKind) to High(TAnchorKind) do begin
SideNode:=FindNode(SelfNode.Sides[a]);
if (SideNode<>nil)
and (SideNode.TheType in [ldcntSplitterLeftRight,ldcntSplitterUpDown])
then begin
if SplitterIsOnlyUsedByNodeAtSide(SideNode,SelfNode,a)
and DockWithOwnSplitter(a) then
exit(true);
inc(SplitterCount);
if (SplitterCount=4) and DockWithSpiralSpltter then
exit(true);
end;
end;
Result:=false;
end; end;
var var
@ -829,10 +866,11 @@ var
begin begin
DebugLn(['TCustomLazControlDocker.RestoreLayout A ',DockerName,' Control=',DbgSName(Control)]); DebugLn(['TCustomLazControlDocker.RestoreLayout A ',DockerName,' Control=',DbgSName(Control)]);
if (Manager=nil) or (Control=nil) then exit; if (Manager=nil) or (Control=nil) then exit;
Layout:=Manager.GetConfigWithDockerName(DockerName); Layout:=Manager.CreateLayout(DockerName,Control,false);
if (Layout=nil) or (Layout.Root=nil) then exit; if (Layout=nil) then exit;
SelfNode:=Layout.Root.FindByName(DockerName,true); try
DebugLn(['TCustomLazControlDocker.RestoreLayout ',SelfNode<>nil,' DockerName=',DockerName,' ',Manager.Configs[0].DockerName]); SelfNode:=Layout.FindByName(DockerName,true);
DebugLn(['TCustomLazControlDocker.RestoreLayout ',SelfNode<>nil,' DockerName=',DockerName]);
if (SelfNode=nil) or (SelfNode.TheType<>ldcntControl) then exit; if (SelfNode=nil) or (SelfNode.TheType<>ldcntControl) then exit;
if SelfNode.Parent<>nil then begin if SelfNode.Parent<>nil then begin
@ -846,8 +884,8 @@ begin
ldcntControl,ldcntForm: ldcntControl,ldcntForm:
begin begin
// this control was docked on a form as child // this control was docked on a form as child
DebugLn(['TCustomLazControlDocker.RestoreLayout TODO restore splitter']); DebugLn(['TCustomLazControlDocker.RestoreLayout restore splitter']);
//FindSibling(SelfNode,akLeft,LeftSibling,LeftSiblingDistance); if SplitterDocking then exit;
end; end;
else else
exit; exit;
@ -860,6 +898,9 @@ begin
Control.SetBoundsKeepBase(NewBounds.Left,NewBounds.Top, Control.SetBoundsKeepBase(NewBounds.Left,NewBounds.Top,
NewBounds.Right-NewBounds.Left, NewBounds.Right-NewBounds.Left,
NewBounds.Bottom-NewBounds.Top); NewBounds.Bottom-NewBounds.Top);
finally
Layout.Free;
end;
end; end;
constructor TCustomLazControlDocker.Create(TheOwner: TComponent); constructor TCustomLazControlDocker.Create(TheOwner: TComponent);
@ -1076,18 +1117,18 @@ var
begin begin
// merge the configs // merge the configs
NewConfigCount:=Config.GetValue(Path+'Configs/Count',0); NewConfigCount:=Config.GetValue(Path+'Configs/Count',0);
DebugLn(['TCustomLazDockingManager.LoadFromConfig NewConfigCount=',NewConfigCount]); //DebugLn(['TCustomLazDockingManager.LoadFromConfig NewConfigCount=',NewConfigCount]);
for i:=0 to NewConfigCount-1 do begin for i:=0 to NewConfigCount-1 do begin
SubPath:=Path+'Config'+IntToStr(i)+'/'; SubPath:=Path+'Config'+IntToStr(i)+'/';
NewDockerName:=Config.GetValue(SubPath+'DockerName/Value',''); NewDockerName:=Config.GetValue(SubPath+'DockerName/Value','');
if NewDockerName='' then continue; if NewDockerName='' then continue;
NewRootName:=Config.GetValue(SubPath+'Name/Value',''); NewRootName:=Config.GetValue(SubPath+'Name/Value','');
if NewRootName='' then continue; if NewRootName='' then continue;
DebugLn(['TCustomLazDockingManager.LoadFromConfig NewDockerName=',NewDockerName,' NewRootName=',NewRootName]); //DebugLn(['TCustomLazDockingManager.LoadFromConfig NewDockerName=',NewDockerName,' NewRootName=',NewRootName]);
NewRoot:=TLazDockConfigNode.Create(nil,NewRootName); NewRoot:=TLazDockConfigNode.Create(nil,NewRootName);
NewRoot.LoadFromConfig(Config,SubPath); NewRoot.LoadFromConfig(Config,SubPath);
AddOrReplaceConfig(NewDockerName,NewRoot); AddOrReplaceConfig(NewDockerName,NewRoot);
NewRoot.WriteDebugReport; //NewRoot.WriteDebugReport;
end; end;
end; end;
@ -1196,18 +1237,18 @@ var
SiblingSide: TAnchorKind): boolean; SiblingSide: TAnchorKind): boolean;
{ check if one side of the Splitter is only used by Node. { check if one side of the Splitter is only used by Node.
For example: If only Node.Sides[SiblingSide]=Splitter.Name For example: If only Node.Sides[SiblingSide]=Splitter.Name
---------+ --------+ ---------+
--+#+---+| ---+| --+#+---+|
B |#| A || -> B || B |#| A ||
--+#+---+| ---+| --+#+---+|
---------+ --------+} ---------+}
begin begin
Result:=FindNodeUsingSplitter(Splitter,SiblingSide,true)<>nil; Result:=FindNodeUsingSplitter(Splitter,SiblingSide,true)<>nil;
end; end;
procedure DeleteNode(var DeletingNode: TLazDockConfigNode); procedure DeleteNode(var DeletingNode: TLazDockConfigNode);
function IsOwnSideSplitter(Side: TAnchorKind; function DeleteOwnSideSplitter(Side: TAnchorKind;
var SplitterNode: TLazDockConfigNode): boolean; var SplitterNode: TLazDockConfigNode): boolean;
{ check if DeletingNode has a splitter to Side, and this node is the only { check if DeletingNode has a splitter to Side, and this node is the only
node anchored to the splitter at this side. node anchored to the splitter at this side.
@ -1227,8 +1268,8 @@ var
begin begin
Result:=false; Result:=false;
// check if this is the only node using this Side of the splitter // check if this is the only node using this Side of the splitter
if not SplitterIsOnlyUsedByNodeAtSide(SplitterNode,DeletingNode, if not SplitterIsOnlyUsedByNodeAtSide(SplitterNode,DeletingNode,Side) then
Side) then exit; exit;
// All nodes, that uses the splitter from the other side will now be // All nodes, that uses the splitter from the other side will now be
// anchored to the other side of DeletingNode // anchored to the other side of DeletingNode
@ -1289,16 +1330,12 @@ var
Result:=true; Result:=true;
end; end;
procedure RaiseUnknownCase;
begin
raise Exception.Create('TCustomLazDockingManager.CreateLayout invalid Config');
end;
var var
a: TAnchorKind; a: TAnchorKind;
SiblingNode: TLazDockConfigNode; SiblingNode: TLazDockConfigNode;
SplitterCount: Integer; SplitterCount: Integer;// number of shared splitters
begin begin
DebugLn(['DeleteNode ',DeletingNode.Name]);
SplitterCount:=0; SplitterCount:=0;
for a:=Low(TAnchorKind) to High(TAnchorKind) do begin for a:=Low(TAnchorKind) to High(TAnchorKind) do begin
SiblingNode:=FindNode(DeletingNode.Sides[a]); SiblingNode:=FindNode(DeletingNode.Sides[a]);
@ -1306,18 +1343,18 @@ var
and (SiblingNode.TheType in [ldcntSplitterLeftRight,ldcntSplitterUpDown]) and (SiblingNode.TheType in [ldcntSplitterLeftRight,ldcntSplitterUpDown])
then begin then begin
// there is a splitter // there is a splitter
if IsOwnSideSplitter(a,SiblingNode) then break; if DeleteOwnSideSplitter(a,SiblingNode) then begin
inc(SplitterCount); // splitter deleted
end; break;
end;
if SplitterCount=0 then begin
// no splitter -> simply delete the node
end else if SplitterCount=4 then begin
// this is a spiral splitter node
UnbindSpiralNode;
end else begin end else begin
// this should never be reached inc(SplitterCount);// not own => shared
RaiseUnknownCase; if SplitterCount=4 then begin
// this is a spiral splitter node -> merge two splitters
UnbindSpiralNode;
break;
end;
end;
end;
end; end;
FreeAndNil(DeletingNode); FreeAndNil(DeletingNode);
end; end;
@ -1361,6 +1398,44 @@ var
end; end;
end; end;
FreeAndNil(PagesNode); FreeAndNil(PagesNode);
//debugln(Root.DebugLayoutAsString);
end;
procedure SimplifyOneChildForm(var FormNode: TLazDockConfigNode);
{ FormNode has only one child left.
Remove Form node and replace root with child
}
var
FormBounds: TRect;
OffsetX: LongInt;
OffsetY: LongInt;
Child: TLazDockConfigNode;
ChildBounds: TRect;
a: TAnchorKind;
OldFormNode: TLazDockConfigNode;
begin
DebugLn(['SimplifyOneChildForm ',dbgs(FormNode)]);
if FormNode<>Root then RaiseGDBException('');
if FormNode.ChildCount<>1 then RaiseGDBException('');
FormBounds:=FormNode.Bounds;
OffsetX:=FormBounds.Left;
OffsetY:=FormBounds.Top;
Child:=FormNode.Childs[0];
// changes parent of child
Child.Parent:=FormNode.Parent;
// move child to place where FormNode was
ChildBounds:=Child.Bounds;
OffsetRect(ChildBounds,OffsetX,OffsetY);
Child.Bounds:=ChildBounds;
// change anchors of child
for a:=Low(TAnchorKind) to High(TAnchorKind) do begin
if CompareText(Child.Sides[a],FormNode.Name)=0 then
Child.Sides[a]:=FormNode.Sides[a];
end;
OldFormNode:=FormNode;
FormNode:=Child;
OldFormNode.Free;
//Root.WriteDebugReport;
end; end;
procedure RemoveEmptyNodes(var Node: TLazDockConfigNode); procedure RemoveEmptyNodes(var Node: TLazDockConfigNode);
@ -1389,24 +1464,39 @@ var
Docker:=FindDockerByName(Node.Name); Docker:=FindDockerByName(Node.Name);
// if the associated control does not exist or is not visible, // if the associated control does not exist or is not visible,
// then delete the node // then delete the node
if (Docker=nil) or not ControlIsVisible(Docker.Control) then begin if (Docker=nil) then begin
DebugLn(['RemoveEmptyNodes delete unknown or invisible node: ',dbgs(Node)]); DebugLn(['RemoveEmptyNodes delete unknown node: ',dbgs(Node)]);
DeleteNode(Node);
end
else if not ControlIsVisible(Docker.Control) then begin
DebugLn(['RemoveEmptyNodes delete invisible node: ',dbgs(Node)]);
DeleteNode(Node); DeleteNode(Node);
end; end;
end; end;
ldcntForm,ldcntPage: ldcntPage:
// these are auto created parent nodes. If they have no childs: delete // these are auto created parent node. If they have no childs: delete
if Node.ChildCount=0 then begin if Node.ChildCount=0 then begin
DebugLn(['RemoveEmptyNodes delete node without childs: ',dbgs(Node)]); DebugLn(['RemoveEmptyNodes delete node without childs: ',dbgs(Node)]);
DeleteNode(Node); DeleteNode(Node);
end; end;
ldcntPages: ldcntForm:
// this is an auto created parent node. If it has no childs: delete // these are auto created parent node. If they have no childs: delete
// if they have only one child: delete node and move childs up
if Node.ChildCount=0 then begin if Node.ChildCount=0 then begin
DebugLn(['RemoveEmptyNodes delete node without childs: ',dbgs(Node)]); DebugLn(['RemoveEmptyNodes delete node without childs: ',dbgs(Node)]);
DeleteNode(Node); DeleteNode(Node);
end else if Node.ChildCount=1 then begin end else if Node.ChildCount=1 then begin
// Only one page left // Only one child left
SimplifyOneChildForm(Node);
end;
ldcntPages:
// these are auto created parent node. If they have no childs: delete
// if they have only one child: delete node and move child up
if Node.ChildCount=0 then begin
DebugLn(['RemoveEmptyNodes delete node without childs: ',dbgs(Node)]);
DeleteNode(Node);
end else if Node.ChildCount=1 then begin
// Only one child left
SimplifyOnePageNode(Node); SimplifyOnePageNode(Node);
end; end;
end; end;
@ -1426,12 +1516,14 @@ var
if (CurForm<>nil) then begin if (CurForm<>nil) then begin
while CurForm.Parent<>nil do while CurForm.Parent<>nil do
CurForm:=CurForm.Parent; CurForm:=CurForm.Parent;
if CurForm<>VisibleControl then begin
if RootForm=nil then if RootForm=nil then
RootForm:=CurForm RootForm:=CurForm
else if RootForm<>CurForm then else if RootForm<>CurForm then
exit(false); exit(false);
end; end;
end; end;
end;
// check childs // check childs
for i:=0 to Node.ChildCount-1 do for i:=0 to Node.ChildCount-1 do
if not Check(Node.Childs[i]) then exit(false); if not Check(Node.Childs[i]) then exit(false);
@ -1577,20 +1669,23 @@ begin
// clean up by removing all invisible, unknown and empty nodes // clean up by removing all invisible, unknown and empty nodes
RemoveEmptyNodes(Root); RemoveEmptyNodes(Root);
DebugLn(['TCustomLazDockingManager.CreateLayout After removing unneeded nodes:']);
Root.WriteDebugReport;
// check if all used controls are on the same dock form // check if all used controls are on the same dock form
if not AllControlsAreOnSameForm then begin if not AllControlsAreOnSameForm then begin
DebugLn(['TCustomLazDockingManager.CreateLayout not all Controls are on the same Form']);
// the used controls are distributed on different dock forms // the used controls are distributed on different dock forms
// => choose one dock form and remove the nodes of the others // => choose one dock form and remove the nodes of the others
NearestControlNode:=FindNearestControlNode; NearestControlNode:=FindNearestControlNode;
if NearestControlNode<>nil then begin if NearestControlNode=nil then RaiseGDBException('');
CurDockControl:=FindControlByDockerName(NearestControlNode.Name); CurDockControl:=FindControlByDockerName(NearestControlNode.Name);
if CurDockControl<>nil then begin if CurDockControl=nil then RaiseGDBException('');
CurDockControl:=CurDockControl.GetTopParent; CurDockControl:=CurDockControl.GetTopParent;
// remove nodes of other dock forms // remove nodes of other dock forms
RemoveEmptyNodes(Root); RemoveEmptyNodes(Root);
end; DebugLn(['TCustomLazDockingManager.CreateLayout After removing nodes of other dock forms:']);
end; Root.WriteDebugReport;
end; end;
Result:=Root; Result:=Root;
@ -1705,6 +1800,26 @@ function TCustomLazDockingManager.ConfigIsCompatible(
Result:=true; Result:=true;
end; end;
function CheckUniqueCorner(Side1, Side2: TAnchorKind): boolean;
var
i: Integer;
Child: TLazDockConfigNode;
begin
Result:=true;
if Node.Parent=nil then exit;
if Node.Sides[Side1]='' then exit;
if Node.Sides[Side2]='' then exit;
for i:=0 to Node.Parent.ChildCount-1 do begin
Child:=Node.Parent.Childs[i];
if Child=Node then continue;
if (CompareText(Node.Sides[Side1],Child.Sides[Side1])=0)
and (CompareText(Node.Sides[Side2],Child.Sides[Side2])=0) then begin
Error('overlapping nodes');
exit(false);
end;
end;
end;
var var
a: TAnchorKind; a: TAnchorKind;
i: Integer; i: Integer;
@ -1790,6 +1905,11 @@ function TCustomLazDockingManager.ConfigIsCompatible(
exit; exit;
end; end;
if not CheckUniqueCorner(akLeft,akTop) then exit;
if not CheckUniqueCorner(akLeft,akBottom) then exit;
if not CheckUniqueCorner(akRight,akTop) then exit;
if not CheckUniqueCorner(akRight,akBottom) then exit;
// check childs // check childs
for i:=0 to Node.ChildCount-1 do for i:=0 to Node.ChildCount-1 do
if not CheckNode(Node.Childs[i]) then exit; if not CheckNode(Node.Childs[i]) then exit;
@ -1928,7 +2048,6 @@ begin
SrcChild:=Src.Childs[i]; SrcChild:=Src.Childs[i];
NewChild:=TLazDockConfigNode.Create(Self); NewChild:=TLazDockConfigNode.Create(Self);
NewChild.Assign(SrcChild); NewChild.Assign(SrcChild);
FChilds.Add(NewChild);
end; end;
end else end else
inherited Assign(Source); inherited Assign(Source);
@ -2075,6 +2194,7 @@ begin
DebugLn('TLazDockConfigNode.WriteDebugReport Root=',dbgs(Self)); DebugLn('TLazDockConfigNode.WriteDebugReport Root=',dbgs(Self));
WriteNode(' ',Self); WriteNode(' ',Self);
DebugLn(DebugLayoutAsString); DebugLn(DebugLayoutAsString);
DumpStack;
end; end;
function TLazDockConfigNode.DebugLayoutAsString: string; function TLazDockConfigNode.DebugLayoutAsString: string;
@ -2118,17 +2238,17 @@ var
Result:=PNodeInfo(NodeInfos[Node]); Result:=PNodeInfo(NodeInfos[Node]);
if Result=nil then begin if Result=nil then begin
New(Result); New(Result);
FillChar(Result^,SizeOf(Result),0); FillChar(Result^,SizeOf(TNodeInfo),0);
NodeInfos[Node]:=Result; NodeInfos[Node]:=Result;
end; end;
end; end;
procedure w(x,y: Integer; const s: string; MaxY: Integer = 0); procedure w(x,y: Integer; const s: string; MaxX: Integer = 0);
var var
i: Integer; i: Integer;
begin begin
for i:=1 to length(s) do begin for i:=1 to length(s) do begin
if (MaxY>0) and (y>MaxY) then exit; if (MaxX>0) and (x+i>MaxX) then exit;
Result[LogCols*(y-1) + x + i-1]:=s[i]; Result[LogCols*(y-1) + x + i-1]:=s[i];
end; end;
end; end;
@ -2200,6 +2320,7 @@ var
NeighbourLength: LongInt; NeighbourLength: LongInt;
begin begin
if Neighbour=nil then exit; if Neighbour=nil then exit;
if Neighbour.Parent<>Node.Parent then exit;
NeighbourPos:=GetMinPos(Neighbour,Side); NeighbourPos:=GetMinPos(Neighbour,Side);
NeighbourSize:=GetMinSize(Neighbour); NeighbourSize:=GetMinSize(Neighbour);
if Side=akLeft then if Side=akLeft then
@ -2215,6 +2336,7 @@ var
begin begin
if MinPosCalculating then begin if MinPosCalculating then begin
DebugLn(['DebugLayoutAsString.GetMinPos.Compute WARNING: anchor circle detected']); DebugLn(['DebugLayoutAsString.GetMinPos.Compute WARNING: anchor circle detected']);
DumpStack;
exit(1); exit(1);
end; end;
if (not MinPosValid) then begin if (not MinPosValid) then begin
@ -2240,6 +2362,7 @@ var
Info: PNodeInfo; Info: PNodeInfo;
begin begin
Info:=GetNodeInfo(Node); Info:=GetNodeInfo(Node);
//DebugLn(['GetMinPos ',Node.Name,' ',AnchorNames[Side],' ',Info^.MinLeftCalculating]);
if Side=akLeft then if Side=akLeft then
Result:=Compute(Info^.MinLeftValid,Info^.MinLeftCalculating,Info^.MinLeft) Result:=Compute(Info^.MinLeftValid,Info^.MinLeftCalculating,Info^.MinLeft)
else else
@ -2254,6 +2377,7 @@ var
Child: TLazDockConfigNode; Child: TLazDockConfigNode;
ChildSize: TPoint; ChildSize: TPoint;
begin begin
//DebugLn(['GetChildsMinSize ',Node.name]);
Result:=Point(0,0); Result:=Point(0,0);
if Node.TheType=ldcntPages then begin if Node.TheType=ldcntPages then begin
// maximum size of all pages // maximum size of all pages
@ -2278,6 +2402,7 @@ var
ChildMinSize: TPoint; ChildMinSize: TPoint;
Info: PNodeInfo; Info: PNodeInfo;
begin begin
//DebugLn(['GetMinSize ',Node.name]);
Info:=GetNodeInfo(Node); Info:=GetNodeInfo(Node);
if Info^.MinSizeValid then begin if Info^.MinSizeValid then begin
Result:=Info^.MinSize; Result:=Info^.MinSize;
@ -2285,6 +2410,7 @@ var
end; end;
if Info^.MinSizeCalculating then begin if Info^.MinSizeCalculating then begin
DebugLn(['DebugLayoutAsString.GetMinSize WARNING: anchor circle detected']); DebugLn(['DebugLayoutAsString.GetMinSize WARNING: anchor circle detected']);
DumpStack;
Result:=Point(1,1); Result:=Point(1,1);
exit; exit;
end; end;
@ -2301,9 +2427,9 @@ var
Result.X:=Max(Result.X,ChildMinSize.X+2); Result.X:=Max(Result.X,ChildMinSize.X+2);
Result.Y:=Max(Result.Y,ChildMinSize.Y+2); Result.Y:=Max(Result.Y,ChildMinSize.Y+2);
end; end;
Info^.MinSizeCalculating:=false;
Info^.MinSize:=Result; Info^.MinSize:=Result;
Info^.MinSizeValid:=true; Info^.MinSizeValid:=true;
Info^.MinSizeCalculating:=false;
end; end;
procedure DrawNode(Node: TLazDockConfigNode; ARect: TRect); procedure DrawNode(Node: TLazDockConfigNode; ARect: TRect);
@ -2311,20 +2437,23 @@ var
i: Integer; i: Integer;
Child: TLazDockConfigNode; Child: TLazDockConfigNode;
ChildSize: TPoint; ChildSize: TPoint;
ChildPos: TPoint;
ChildRect: TRect; ChildRect: TRect;
begin begin
//DebugLn(['DrawNode Node=',Node.Name,' ARect=',dbgs(ARect)]);
wrectangle(ARect); wrectangle(ARect);
w(ARect.Left+1,ARect.Top,Node.Name,ARect.Right); w(ARect.Left+1,ARect.Top,Node.Name,ARect.Right);
for i := 0 to Node.ChildCount-1 do begin for i := 0 to Node.ChildCount-1 do begin
Child:=Node.Childs[i]; Child:=Node.Childs[i];
ChildRect.Left:=ARect.Left+1+GetMinPos(Child,akLeft);
ChildRect.Top:=ARect.Top+1+GetMinPos(Child,akTop);
ChildSize:=GetMinSize(Child); ChildSize:=GetMinSize(Child);
ChildPos:=Point(GetMinPos(Child,akLeft),GetMinPos(Child,akTop));
ChildRect.Left:=ARect.Left+1+ChildPos.X;
ChildRect.Top:=ARect.Top+1+ChildPos.Y;
ChildRect.Right:=ChildRect.Left+ChildSize.X-1; ChildRect.Right:=ChildRect.Left+ChildSize.X-1;
ChildRect.Bottom:=ChildRect.Top+ChildSize.Y-1; ChildRect.Bottom:=ChildRect.Top+ChildSize.Y-1;
if CompareText(Child.Sides[akRight],Node.Name)=0 then
ChildRect.Right:=ARect.Right-1;
if CompareText(Child.Sides[akBottom],Node.Name)=0 then
ChildRect.Bottom:=ARect.Bottom-1;
DrawNode(Child,ChildRect); DrawNode(Child,ChildRect);
if Node.TheType=ldcntPages then begin if Node.TheType=ldcntPages then begin
// paint only one page // paint only one page