lazarus/lcl/ldockctrl.pas
mattias 34318f3f2b added comctrls ttreenode docs from Darius
git-svn-id: trunk@9063 -
2006-04-02 17:30:45 +00:00

801 lines
24 KiB
ObjectPascal

{ $Id: ldocktree.pas 8153 2005-11-14 21:53:06Z mattias $ }
{
/***************************************************************************
LDockCtrl.pas
-----------------
***************************************************************************/
*****************************************************************************
* *
* This file is part of the Lazarus Component Library (LCL) *
* *
* See the file COPYING.LCL, included in this distribution, *
* for details about the copyright. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
*****************************************************************************
Author: Mattias Gaertner
Abstract:
This unit contains visual components for docking and streaming.
ToDo:
- restoring layout, when a docked control becomes visible
- save TLazDockConfigNode to stream
- load TLazDockConfigNode from stream
}
unit LDockCtrl;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, TypInfo, LCLProc, Controls, Forms, Menus, LCLStrConsts,
StringHashList, LDockCtrlEdit, LDockTree;
type
TNonDockConfigNames = (
ndcnControlName, // '-Name ' + AControl.Name
ndcnChildIndex, // '-ID ' + IntToStr(AControl index in Parent) + AControl.ClassName
ndcnParent // '-Parent' : AControl.Parent
);
const
NonDockConfigNamePrefixes: array[TNonDockConfigNames] of string = (
'-Name ',
'-ID ',
'-Parent');
type
TLDConfigNodeType = (
ldcntControl,
ldcntForm,
ldcntSplitter,
ldcntPages,
ldcntPage
);
{ TLazDockConfigNode }
TLazDockConfigNode = class(TPersistent)
private
FBounds: TRect;
FName: string;
FParent: TLazDockConfigNode;
FSides: array[TAnchorKind] of TLazDockConfigNode;
FTheType: TLDConfigNodeType;
FChilds: TFPList;
function GetChildCount: Integer;
function GetChilds(Index: integer): TLazDockConfigNode;
function GetSides(Side: TAnchorKind): TLazDockConfigNode;
procedure SetBounds(const AValue: TRect);
procedure SetName(const AValue: string);
procedure SetParent(const AValue: TLazDockConfigNode);
procedure SetSides(Side: TAnchorKind; const AValue: TLazDockConfigNode);
procedure SetTheType(const AValue: TLDConfigNodeType);
procedure DoAdd(ChildNode: TLazDockConfigNode);
procedure DoRemove(ChildNode: TLazDockConfigNode);
public
constructor Create(ParentNode: TLazDockConfigNode; const AName: string);
destructor Destroy; override;
procedure Clear;
function FindByName(const AName: string): TLazDockConfigNode;
public
property Bounds: TRect read FBounds write SetBounds;
property Parent: TLazDockConfigNode read FParent write SetParent;
property Sides[Side: TAnchorKind]: TLazDockConfigNode read GetSides write SetSides;
property ChildCount: Integer read GetChildCount;
property Childs[Index: integer]: TLazDockConfigNode read GetChilds; default;
published
property TheType: TLDConfigNodeType read FTheType write SetTheType;
property Name: string read FName write SetName;
end;
TCustomLazControlDocker = class;
{ TCustomLazDockingManager }
TCustomLazDockingManager = class(TComponent)
private
FDockers: TFPList;
FManager: TAnchoredDockManager;
function GetDockerCount: Integer;
function GetDockers(Index: Integer): TCustomLazControlDocker;
protected
procedure Remove(Docker: TCustomLazControlDocker);
function Add(Docker: TCustomLazControlDocker): Integer;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
function FindDockerByName(const ADockerName: string;
Ignore: TCustomLazControlDocker): TCustomLazControlDocker;
function FindDockerByControl(AControl: TControl;
Ignore: TCustomLazControlDocker): TCustomLazControlDocker;
function CreateUniqueName(const AName: string;
Ignore: TCustomLazControlDocker): string;
procedure SaveToStream(Stream: TStream);
function GetControlConfigName(AControl: TControl): string;
procedure WriteDebugReport;
public
property Manager: TAnchoredDockManager read FManager;
property DockerCount: Integer read GetDockerCount;
property Dockers[Index: Integer]: TCustomLazControlDocker read GetDockers; default;
end;
{ TLazDockingManager }
TLazDockingManager = class(TCustomLazDockingManager)
published
end;
{ TCustomLazControlDocker
A component to connect a form to the TLazDockingManager.
When the control gets visible TCustomLazControlDocker restores the layout.
Before the control gets invisible, TCustomLazControlDocker saves the layout.
}
TCustomLazControlDocker = class(TComponent)
private
FConfigRootNode: TLazDockConfigNode;// the root node of the config tree
FConfigSelfNode: TLazDockConfigNode;// the node of 'Control'
FControl: TControl;
FDockerName: string;
FExtendPopupMenu: boolean;
FLocalizedName: string;
FManager: TCustomLazDockingManager;
FPopupMenuItem: TMenuItem;
procedure SetControl(const AValue: TControl);
procedure SetDockerName(const AValue: string);
procedure SetExtendPopupMenu(const AValue: boolean);
procedure SetLocalizedName(const AValue: string);
procedure SetManager(const AValue: TCustomLazDockingManager);
procedure PopupMenuItemClick(Sender: TObject);
protected
procedure UpdatePopupMenu; virtual;
procedure Loaded; override;
function GetLocalizedName: string;
procedure ControlVisibleChanging(Sender: TObject);
procedure ControlVisibleChanged(Sender: TObject);
public
procedure ShowDockingEditor; virtual;
procedure ClearConfigNodes;
procedure GetLayoutFromControl;
function GetControlName(AControl: TControl): string;
procedure WriteConfigTreeDebugReport;
constructor Create(TheOwner: TComponent); override;
property Control: TControl read FControl write SetControl;
property Manager: TCustomLazDockingManager read FManager write SetManager;
property ExtendPopupMenu: boolean read FExtendPopupMenu write SetExtendPopupMenu;
property PopupMenuItem: TMenuItem read FPopupMenuItem;
property LocalizedName: string read FLocalizedName write SetLocalizedName;
property DockerName: string read FDockerName write SetDockerName;
property ConfigRootNode: TLazDockConfigNode read FConfigRootNode;
property ConfigSelfNode: TLazDockConfigNode read FConfigSelfNode;
end;
{ TLazControlDocker }
TLazControlDocker = class(TCustomLazControlDocker)
published
property Control;
property Manager;
property ExtendPopupMenu;
property DockerName;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Misc',[TLazDockingManager,TLazControlDocker]);
end;
{ TCustomLazControlDocker }
procedure TCustomLazControlDocker.SetManager(
const AValue: TCustomLazDockingManager);
begin
if FManager=AValue then exit;
//DebugLn('TCustomLazControlDocker.SetManager Old=',DbgSName(Manager),' New=',DbgSName(AValue));
if FManager<>nil then FManager.Remove(Self);
FManager:=AValue;
if FManager<>nil then FManager.Add(Self);
UpdatePopupMenu;
end;
procedure TCustomLazControlDocker.UpdatePopupMenu;
// creates or deletes the PopupMenuItem to the PopupMenu of Control
begin
if [csDestroying,csDesigning]*ComponentState<>[] then exit;
if csLoading in ComponentState then exit;
//DebugLn('TCustomLazControlDocker.UpdatePopupMenu ',DbgSName(Control),' Manager=',DbgSName(Manager),' PopupMenu=',dbgs((Control<>nil) and (Control.PopupMenu<>nil)),' ExtendPopupMenu=',dbgs(ExtendPopupMenu));
if ExtendPopupMenu and (Control<>nil) and (Control.PopupMenu<>nil)
and (Manager<>nil) then begin
//DebugLn('TCustomLazControlDocker.UpdatePopupMenu ADDING');
if (PopupMenuItem<>nil) and (PopupMenuItem.Parent<>Control.PopupMenu.Items)
then begin
// PopupMenuItem is in the old PopupMenu -> delete it
FreeAndNil(FPopupMenuItem);
end;
if (PopupMenuItem=nil) then begin
// create a new PopupMenuItem
FPopupMenuItem:=TMenuItem.Create(Self);
PopupMenuItem.Caption:=rsDocking;
PopupMenuItem.OnClick:=@PopupMenuItemClick;
end;
if PopupMenuItem.Parent=nil then begin
// add PopupMenuItem to Control.PopupMenu
Control.PopupMenu.Items.Add(PopupMenuItem);
end;
end else begin
// delete PopupMenuItem
FreeAndNil(FPopupMenuItem);
end;
end;
procedure TCustomLazControlDocker.Loaded;
begin
inherited Loaded;
UpdatePopupMenu;
end;
procedure TCustomLazControlDocker.ShowDockingEditor;
var
Dlg: TLazDockControlEditorDlg;
i: Integer;
TargetDocker: TCustomLazControlDocker;
Side: TAlign;
CurDocker: TCustomLazControlDocker;
begin
Dlg:=TLazDockControlEditorDlg.Create(nil);
try
// fill the list of controls this control can dock to
Dlg.DockControlComboBox.Text:='';
Dlg.DockControlComboBox.Items.BeginUpdate;
//DebugLn('TCustomLazControlDocker.ShowDockingEditor Self=',DockerName,' Manager.DockerCount=',dbgs(Manager.DockerCount));
try
Dlg.DockControlComboBox.Items.Clear;
for i:=0 to Manager.DockerCount-1 do begin
CurDocker:=Manager.Dockers[i];
//DebugLn('TCustomLazControlDocker.ShowDockingEditor Self=',DockerName,' CurDocker=',CurDocker.DockerName);
if CurDocker=Self then continue;
if CurDocker.Control=nil then continue;
Dlg.DockControlComboBox.Items.Add(CurDocker.GetLocalizedName);
end;
Dlg.DockControlComboBox.Enabled:=Dlg.DockControlComboBox.Items.Count>0;
finally
Dlg.DockControlComboBox.Items.EndUpdate;
end;
// enable Undock button, if Control is docked
Dlg.UndockGroupBox.Enabled:=(Control.Parent<>nil)
and (Control.Parent.ControlCount>1);
if Dlg.ShowModal=mrOk then begin
// dock or undock
case Dlg.DlgResult of
ldcedrUndock:
// undock
Manager.Manager.UndockControl(Control,true);
ldcedrDockLeft,ldcedrDockRight,ldcedrDockTop,
ldcedrDockBottom,ldcedrDockPage:
// dock
begin
TargetDocker:=nil;
for i:=0 to Manager.DockerCount-1 do begin
CurDocker:=Manager.Dockers[i];
if CurDocker=Self then continue;
if Dlg.DockControlComboBox.Text=CurDocker.GetLocalizedName then
TargetDocker:=CurDocker;
end;
if TargetDocker=nil then begin
RaiseGDBException('TCustomLazControlDocker.ShowDockingEditor TargetDocker=nil');
end;
case Dlg.DlgResult of
ldcedrDockLeft: Side:=alLeft;
ldcedrDockRight: Side:=alRight;
ldcedrDockTop: Side:=alTop;
ldcedrDockBottom: Side:=alBottom;
ldcedrDockPage: Side:=alClient;
else RaiseGDBException('TCustomLazControlDocker.ShowDockingEditor ?');
end;
Manager.Manager.DockControl(Control,Side,TargetDocker.Control);
end;
end;
end;
finally
Dlg.Free;
end;
end;
function TCustomLazControlDocker.GetLocalizedName: string;
begin
Result:=LocalizedName;
if LocalizedName='' then begin
Result:=DockerName;
if (Result='') and (Control<>nil) then
Result:=Control.Name;
if Result='' then
Result:=Name;
end;
end;
procedure TCustomLazControlDocker.ControlVisibleChanging(Sender: TObject);
begin
if Control<>Sender then begin
DebugLn('TCustomLazControlDocker.ControlVisibleChanging WARNING: ',
DbgSName(Control),'<>',DbgSName(Sender));
exit;
end;
if Control.Visible then begin
// control will be hidden -> the layout will change
// save the layout for restore
GetLayoutFromControl;
end else begin
// the control will become visible -> dock it to restore the last layout
debugln('TCustomLazControlDocker.ControlVisibleChanging TODO restore layout');
end;
end;
procedure TCustomLazControlDocker.ControlVisibleChanged(Sender: TObject);
begin
end;
function TCustomLazControlDocker.GetControlName(AControl: TControl): string;
var
i: Integer;
begin
Result:=Manager.GetControlConfigName(AControl);
if Result='' then begin
if AControl=Control.Parent then
Result:=NonDockConfigNamePrefixes[ndcnParent]
else if AControl.Name<>'' then
Result:=NonDockConfigNamePrefixes[ndcnControlName]+AControl.Name
else if AControl.Parent<>nil then begin
i:=AControl.Parent.ControlCount-1;
while (i>=0) and (AControl.Parent.Controls[i]<>AControl) do dec(i);
Result:=NonDockConfigNamePrefixes[ndcnChildIndex]+IntToStr(i)
+AControl.ClassName;
end;
end;
end;
procedure TCustomLazControlDocker.GetLayoutFromControl;
procedure CopyChildsLayout(ParentNode: TLazDockConfigNode;
ParentNodeControl: TWinControl);
// saves for each child node the names of the anchor side controls
var
i: Integer;
ChildNode: TLazDockConfigNode;
ChildControl: TControl;
a: TAnchorKind;
ChildNames: TStringHashList;// name to control mapping
ChildName: String;
CurAnchorControl: TControl;
CurAnchorCtrlName: String;
CurAnchorNode: TLazDockConfigNode;
begin
ChildNames:=TStringHashList.Create(false);
try
// build mapping of name to control
ChildNames.Data[ParentNode.Name]:=ParentNodeControl;
for i:=0 to ParentNodeControl.ControlCount-1 do begin
ChildControl:=ParentNodeControl.Controls[i];
ChildName:=GetControlName(ChildControl);
if ChildName<>'' then
ChildNames.Data[ChildName]:=ChildControl;
end;
// build mapping control to node
// set 'Sides'
for i:=0 to ParentNode.ChildCount-1 do begin
ChildNode:=ParentNode[i];
ChildControl:=TControl(ChildNames.Data[ChildNode.Name]);
if ChildControl=nil then continue;
for a:=Low(TAnchorKind) to High(TAnchorKind) do begin
CurAnchorControl:=ChildControl.AnchorSide[a].Control;
if CurAnchorControl=nil then continue;
if CurAnchorControl=ParentNodeControl then
CurAnchorNode:=ParentNode
else begin
CurAnchorCtrlName:=GetControlName(CurAnchorControl);
CurAnchorNode:=ParentNode.FindByName(CurAnchorCtrlName);
if CurAnchorNode=nil then
RaiseGDBException('inconsistency');
end;
DebugLn('CopyChildsLayout ',DbgSName(CurAnchorControl),' CurAnchorCtrlName="',CurAnchorCtrlName,'"');
ChildNode.Sides[a]:=CurAnchorNode;
end;
end;
finally
ChildNames.Free;
end;
end;
function AddNode(ParentNode: TLazDockConfigNode;
AControl: TControl): TLazDockConfigNode;
var
i: Integer;
CurChildControl: TControl;
NeedChildNodes: boolean;
begin
Result:=TLazDockConfigNode.Create(ParentNode,GetControlName(AControl));
if AControl=Control then
FConfigSelfNode:=Result;
// The Type
if AControl is TLazDockSplitter then
Result.FTheType:=ldcntSplitter
else if AControl is TLazDockForm then
Result.FTheType:=ldcntForm
else if AControl is TLazDockPages then
Result.FTheType:=ldcntPages
else if AControl is TLazDockPage then
Result.FTheType:=ldcntPage
else
Result.FTheType:=ldcntControl;
// Bounds
Result.FBounds:=AControl.BoundsRect;
// Childs
if (AControl is TWinControl) then begin
// check if childs need nodes
NeedChildNodes:=(AControl is TLazDockPages)
or (AControl is TLazDockPage);
if not NeedChildNodes then begin
for i:=0 to TWinControl(AControl).ControlCount-1 do begin
CurChildControl:=TWinControl(AControl).Controls[i];
if Manager.FindDockerByControl(CurChildControl,nil)<>nil then begin
NeedChildNodes:=true;
break;
end;
end;
end;
// add child nodes
if NeedChildNodes then begin
for i:=0 to TWinControl(AControl).ControlCount-1 do begin
CurChildControl:=TWinControl(AControl).Controls[i];
AddNode(Result,CurChildControl);
end;
for i:=0 to Result.ChildCount-1 do begin
end;
end;
CopyChildsLayout(Result,TWinControl(AControl));
end;
end;
var
RootControl: TControl;
begin
ClearConfigNodes;
if (Control=nil) or (Manager=nil) then exit;
RootControl:=Control;
while RootControl.Parent<>nil do
RootControl:=RootControl.Parent;
FConfigRootNode:=AddNode(nil,RootControl);
end;
procedure TCustomLazControlDocker.ClearConfigNodes;
begin
FConfigSelfNode:=nil;
FConfigRootNode.Free;
FConfigRootNode:=nil;
end;
procedure TCustomLazControlDocker.WriteConfigTreeDebugReport;
procedure WriteNode(const Prefix: string; ANode: TLazDockConfigNode);
var
a: TAnchorKind;
i: Integer;
s: string;
begin
if ANode=nil then exit;
DbgOut(Prefix,'Name="'+ANode.Name+'"');
DbgOut(' Type=',GetEnumName(TypeInfo(TLDConfigNodeType),ord(ANode.TheType)));
DbgOut(' Bounds='+dbgs(ANode.Bounds));
DbgOut(' Childs='+dbgs(ANode.ChildCount));
for a:=Low(TAnchorKind) to High(TAnchorKind) do begin
if ANode.Sides[a]=nil then continue;
s:=ANode.Sides[a].Name;
if s='' then
s:='?';
DbgOut(' '+AnchorNames[a]+'="'+s+'"');
end;
debugln;
for i:=0 to ANode.ChildCount-1 do begin
WriteNode(Prefix+' ',ANode[i]);
end;
end;
begin
DebugLn('TCustomLazControlDocker.WriteConfigTreeDebugReport '
,' Root=',dbgs(ConfigRootNode),' SelfNode=',dbgs(ConfigSelfNode));
WriteNode(' ',ConfigRootNode);
end;
constructor TCustomLazControlDocker.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
if (not (csLoading in ComponentState))
and (TheOwner is TControl) then
// use as default
Control:=TControl(TheOwner);
ExtendPopupMenu:=true;
end;
procedure TCustomLazControlDocker.PopupMenuItemClick(Sender: TObject);
begin
ShowDockingEditor;
end;
procedure TCustomLazControlDocker.SetControl(const AValue: TControl);
begin
if FControl=AValue then exit;
if FControl<>nil then
FControl.RemoveAllHandlersOfObject(Self);
FControl:=AValue;
if FControl=nil then begin
FControl.AddHandlerOnVisibleChanging(@ControlVisibleChanging);
FControl.AddHandlerOnVisibleChanged(@ControlVisibleChanged);
end;
if DockerName='' then
DockerName:=AValue.Name;
UpdatePopupMenu;
end;
procedure TCustomLazControlDocker.SetDockerName(const AValue: string);
var
NewDockerName: String;
begin
if FDockerName=AValue then exit;
NewDockerName:=AValue;
if Manager<>nil then
NewDockerName:=Manager.CreateUniqueName(NewDockerName,Self);
FDockerName:=NewDockerName;
end;
procedure TCustomLazControlDocker.SetExtendPopupMenu(const AValue: boolean);
begin
if FExtendPopupMenu=AValue then exit;
FExtendPopupMenu:=AValue;
UpdatePopupMenu;
end;
procedure TCustomLazControlDocker.SetLocalizedName(const AValue: string);
begin
if FLocalizedName=AValue then exit;
FLocalizedName:=AValue;
end;
{ TCustomLazDockingManager }
procedure TCustomLazDockingManager.Remove(Docker: TCustomLazControlDocker);
begin
FDockers.Remove(Docker);
end;
function TCustomLazDockingManager.Add(Docker: TCustomLazControlDocker): Integer;
begin
Docker.DockerName:=CreateUniqueName(Docker.DockerName,nil);
Result:=FDockers.Add(Docker);
end;
function TCustomLazDockingManager.GetDockers(Index: Integer
): TCustomLazControlDocker;
begin
Result:=TCustomLazControlDocker(FDockers[Index]);
end;
function TCustomLazDockingManager.GetDockerCount: Integer;
begin
Result:=FDockers.Count;
end;
constructor TCustomLazDockingManager.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
FDockers:=TFPList.Create;
FManager:=TAnchoredDockManager.Create;
end;
destructor TCustomLazDockingManager.Destroy;
var
i: Integer;
begin
for i:=FDockers.Count-1 downto 0 do
Dockers[i].Manager:=nil;
FreeAndNil(FDockers);
FreeAndNil(FManager);
inherited Destroy;
end;
function TCustomLazDockingManager.FindDockerByName(const ADockerName: string;
Ignore: TCustomLazControlDocker): TCustomLazControlDocker;
var
i: Integer;
begin
i:=DockerCount-1;
while (i>=0) do begin
Result:=Dockers[i];
if (CompareText(Result.DockerName,ADockerName)=0) and (Ignore<>Result) then
exit;
dec(i);
end;
Result:=nil;
end;
function TCustomLazDockingManager.FindDockerByControl(AControl: TControl;
Ignore: TCustomLazControlDocker): TCustomLazControlDocker;
var
i: Integer;
begin
i:=DockerCount-1;
while (i>=0) do begin
Result:=Dockers[i];
if (Result.Control=AControl) and (Ignore<>Result) then
exit;
dec(i);
end;
Result:=nil;
end;
function TCustomLazDockingManager.CreateUniqueName(const AName: string;
Ignore: TCustomLazControlDocker): string;
begin
Result:=AName;
if FindDockerByName(Result,Ignore)=nil then exit;
Result:=CreateFirstIdentifier(Result);
while FindDockerByName(Result,Ignore)<>nil do
Result:=CreateNextIdentifier(Result);
end;
procedure TCustomLazDockingManager.SaveToStream(Stream: TStream);
begin
RaiseGDBException('TODO TCustomLazDockingManager.SaveToStream');
end;
function TCustomLazDockingManager.GetControlConfigName(AControl: TControl
): string;
var
Docker: TCustomLazControlDocker;
begin
Docker:=FindDockerByControl(AControl,nil);
if Docker<>nil then
Result:=Docker.DockerName
else
Result:='';
end;
procedure TCustomLazDockingManager.WriteDebugReport;
var
i: Integer;
ADocker: TCustomLazControlDocker;
begin
DebugLn('TCustomLazDockingManager.WriteDebugReport DockerCount=',dbgs(DockerCount));
for i:=0 to DockerCount-1 do begin
ADocker:=Dockers[i];
DebugLn(' ',dbgs(i),' Name="',ADocker.Name,'" DockerName="',ADocker.DockerName,'"');
end;
end;
{ TLazDockConfigNode }
function TLazDockConfigNode.GetSides(Side: TAnchorKind): TLazDockConfigNode;
begin
Result:=FSides[Side];
end;
function TLazDockConfigNode.GetChildCount: Integer;
begin
if FChilds<>nil then
Result:=FChilds.Count
else
Result:=0;
end;
function TLazDockConfigNode.GetChilds(Index: integer): TLazDockConfigNode;
begin
Result:=TLazDockConfigNode(FChilds[Index]);
end;
procedure TLazDockConfigNode.SetBounds(const AValue: TRect);
begin
if CompareRect(@FBounds,@AValue) then exit;
FBounds:=AValue;
end;
procedure TLazDockConfigNode.SetName(const AValue: string);
begin
if FName=AValue then exit;
FName:=AValue;
end;
procedure TLazDockConfigNode.SetParent(const AValue: TLazDockConfigNode);
begin
if FParent=AValue then exit;
if FParent<>nil then
FParent.DoRemove(Self);
FParent:=AValue;
if FParent<>nil then
FParent.DoAdd(Self);
end;
procedure TLazDockConfigNode.SetSides(Side: TAnchorKind;
const AValue: TLazDockConfigNode);
begin
FSides[Side]:=AValue;
end;
procedure TLazDockConfigNode.SetTheType(const AValue: TLDConfigNodeType);
begin
if FTheType=AValue then exit;
FTheType:=AValue;
end;
procedure TLazDockConfigNode.DoAdd(ChildNode: TLazDockConfigNode);
begin
if FChilds=nil then FChilds:=TFPList.Create;
FChilds.Add(ChildNode);
end;
procedure TLazDockConfigNode.DoRemove(ChildNode: TLazDockConfigNode);
begin
FChilds.Remove(ChildNode);
end;
constructor TLazDockConfigNode.Create(ParentNode: TLazDockConfigNode;
const AName: string);
begin
FName:=AName;
Parent:=ParentNode;
end;
destructor TLazDockConfigNode.Destroy;
begin
Clear;
FChilds.Free;
FChilds:=nil;
inherited Destroy;
end;
procedure TLazDockConfigNode.Clear;
var
i: Integer;
begin
if FChilds=nil then exit;
for i:=ChildCount-1 downto 0 do Childs[i].Free;
FChilds.Clear;
end;
function TLazDockConfigNode.FindByName(const AName: string
): TLazDockConfigNode;
var
i: Integer;
begin
if FChilds<>nil then
for i:=0 to FChilds.Count-1 do begin
Result:=Childs[i];
if CompareText(Result.Name,AName)=0 then exit;
end;
Result:=nil;
end;
end.