home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d56 / RMCTL.ZIP / rmDGT.pas < prev    next >
Pascal/Delphi Source File  |  2001-06-22  |  21KB  |  866 lines

  1. {================================================================================
  2. Copyright (C) 1997-2001 Mills Enterprise
  3.  
  4. Unit     : rmDGT
  5. Purpose  : To have a non-visual Directed Graph Tree component.
  6. Date     : 04-10-2001
  7. Author   : Ryan J. Mills
  8. Version  : 1.80
  9. Notes    : This unit was partially based upon the work of Patrick O'Keeffe.
  10. ================================================================================}
  11.  
  12. unit rmDGT;
  13.  
  14. interface
  15.  
  16. {$I CompilerDefines.INC}
  17.  
  18. uses
  19.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
  20.  
  21. type
  22.   { TTreeNode }
  23.   TAddMode = (taAddFirst, taAdd, taInsert);
  24.   TNodeAttachMode = (naAdd, naAddFirst, naAddChild, naAddChildFirst, naInsert);
  25.  
  26.   PDGNodeInfo = ^TDGNodeInfo;
  27.   TDGNodeInfo = packed record
  28.     Count: Integer;
  29.     Index : integer;
  30.     Text: Char;
  31.   end;
  32.  
  33.   TrmCustomDGTree = class;
  34.   TrmDGTreeNodes = class;
  35.   TrmDGTreeNode = class;
  36.  
  37.   TrmDGTreeNode = class(TPersistent)
  38.   private
  39.     FOwner: TrmDGTreeNodes;
  40.     FText: Char;
  41.     FData: Integer;
  42.     FChildList : TList;
  43.     FDeleting: Boolean;
  44.     FParent: TrmDGTreeNode;
  45.     function GetLevel: Integer;
  46.     function GetParent: TrmDGTreeNode;
  47.     procedure SetParent(Value : TrmDGTreeNode);
  48.     function GetChildren: Boolean;
  49.     function GetIndex: Integer;
  50.     function GetItem(Index: Integer): TrmDGTreeNode;
  51.     function GetCount: Integer;
  52.     function GeTrmDGTree: TrmCustomDGTree;
  53.     function IsEqual(Node: TrmDGTreeNode): Boolean;
  54.     procedure ReadData(Stream: TStream; Info: PDGNodeInfo);
  55.     procedure SetData(Value: Integer);
  56.     procedure SetItem(Index: Integer; Value: TrmDGTreeNode);
  57.     procedure SetText(const S: Char);
  58.     procedure WriteData(Stream: TStream; Info: PDGNodeInfo);
  59.   public
  60.     constructor Create(AOwner: TrmDGTreeNodes);
  61.     destructor Destroy; override;
  62.     procedure Assign(Source: TPersistent); override;
  63.     procedure Delete;
  64.     procedure DeleteChildren;
  65.     function GetFirstChild: TrmDGTreeNode;
  66.     function GetLastChild: TrmDGTreeNode;
  67.     function GetNext: TrmDGTreeNode;
  68.     function GetNextChild(Value: TrmDGTreeNode): TrmDGTreeNode;
  69.     function GetNextSibling: TrmDGTreeNode;
  70.     function GetPrev: TrmDGTreeNode;
  71.     function GetPrevChild(Value: TrmDGTreeNode): TrmDGTreeNode;
  72.     function getPrevSibling: TrmDGTreeNode;
  73.     function HasAsParent(Value: TrmDGTreeNode): Boolean;
  74.     function IndexOf(Value: TrmDGTreeNode): Integer;
  75.     function MoveTo(Destination: TrmDGTreeNode; Mode: TNodeAttachMode):TrmDGTreeNode;
  76.  
  77.     property Count: Integer read GetCount;
  78.     property Data: Integer read FData write SetData;
  79.     property Deleting: Boolean read FDeleting;
  80.     property HasChildren: Boolean read GetChildren;
  81.     property Index: Integer read GetIndex;
  82.     property Item[Index: Integer]: TrmDGTreeNode read GetItem write SetItem; default;
  83.     property Level: Integer read GetLevel;
  84.     property Owner: TrmDGTreeNodes read FOwner;
  85.     property Parent: TrmDGTreeNode read GetParent write SetParent;
  86.     property DGTree: TrmCustomDGTree read GeTrmDGTree;
  87.     property Text: Char read FText write SetText;
  88.   end;
  89.  
  90.   TrmDGTreeNodes = class(TPersistent)
  91.   private
  92.     FOwner: TrmCustomDGTree;
  93.     FRootNodeList : TList;
  94.     function GetNodeFromIndex(Index: Integer): TrmDGTreeNode;
  95.     procedure ReadData(Stream: TStream);
  96.     procedure WriteData(Stream: TStream);
  97.   protected
  98.     function InternalAddObject(Node: TrmDGTreeNode; const S: Char;
  99.       Ptr: Integer; AddMode: TAddMode): TrmDGTreeNode;
  100.     procedure DefineProperties(Filer: TFiler); override;
  101.     function GetCount: Integer;
  102.     procedure SetItem(Index: Integer; Value: TrmDGTreeNode);
  103.   public
  104.     constructor Create(AOwner: TrmCustomDGTree);
  105.     destructor Destroy; override;
  106.     function AddChildFirst(Node: TrmDGTreeNode; const S: Char): TrmDGTreeNode;
  107.     function AddChild(Node: TrmDGTreeNode; const S: Char): TrmDGTreeNode;
  108.     function AddChildObjectFirst(Node: TrmDGTreeNode; const S: Char;
  109.       Ptr: Integer): TrmDGTreeNode;
  110.     function AddChildObject(Node: TrmDGTreeNode; const S: Char;
  111.       Ptr: Integer): TrmDGTreeNode;
  112.     function AddFirst(Node: TrmDGTreeNode; const S: Char): TrmDGTreeNode;
  113.     function Add(Node: TrmDGTreeNode; const S: Char): TrmDGTreeNode;
  114.     function AddObjectFirst(Node: TrmDGTreeNode; const S: Char;
  115.       Ptr: Integer): TrmDGTreeNode;
  116.     function AddObject(Node: TrmDGTreeNode; const S: Char;
  117.       Ptr: Integer): TrmDGTreeNode;
  118.     procedure Assign(Source: TPersistent); override;
  119.     procedure Clear;
  120.     procedure Delete(Node: TrmDGTreeNode);
  121.     function GetFirstNode: TrmDGTreeNode;
  122.     function Insert(Node: TrmDGTreeNode; const S: Char): TrmDGTreeNode;
  123.     function InsertObject(Node: TrmDGTreeNode; const S: Char;
  124.       Ptr: Integer): TrmDGTreeNode;
  125.     property Count: Integer read GetCount;
  126.     property Item[Index: Integer]: TrmDGTreeNode read GetNodeFromIndex; default;
  127.     property Owner: TrmCustomDGTree read FOwner;
  128.   end;
  129.  
  130. { TDGCustomDGTree }
  131.  
  132.   TrmDGTreeEvent = procedure(Sender: TObject; Node: TrmDGTreeNode) of object;
  133.   EDGTreeError = class(Exception);
  134.  
  135.   TrmCustomDGTree = class(TComponent)
  136.   private
  137.     FMemStream: TMemoryStream;
  138.     FTreeNodes: TrmDGTreeNodes;
  139.     FOnDeletion: TrmDGTreeEvent;
  140.     procedure SetrmDGTreeNodes(Value: TrmDGTreeNodes);
  141.   protected
  142.     function CreateNode: TrmDGTreeNode; virtual;
  143.     procedure Delete(Node: TrmDGTreeNode); dynamic;
  144.     property Items: TrmDGTreeNodes read FTreeNodes write SeTrmDGTreeNodes;
  145.     property OnDeletion: TrmDGTreeEvent read FOnDeletion write FOnDeletion;
  146.   public
  147.     constructor Create(AOwner: TComponent); override;
  148.     destructor Destroy; override;
  149.   end;
  150.  
  151.   TrmDGTree = class(TrmCustomDGTree)
  152.   private
  153.     { Private declarations }
  154.   protected
  155.     { Protected declarations }
  156.   public
  157.     { Public declarations }
  158.   published
  159.     { Published declarations }
  160.     property Items;
  161.     property OnDeletion;
  162.   end;
  163.  
  164. implementation
  165.  
  166. procedure DGTreeError(const Msg: string);
  167. begin
  168.   raise EDGTreeError.Create(Msg);
  169. end;
  170.  
  171. constructor TrmDGTreeNode.Create(AOwner: TrmDGTreeNodes);
  172. begin
  173.   inherited Create;
  174.   FOwner := AOwner;
  175.   FChildList := TList.Create;
  176. end;
  177.  
  178. destructor TrmDGTreeNode.Destroy;
  179. begin
  180.   FDeleting := True;
  181.   FChildList.Free;
  182.   inherited Destroy;
  183. end;
  184.  
  185. function TrmDGTreeNode.GeTrmDGTree: TrmCustomDGTree;
  186. begin
  187.   Result := Owner.Owner;
  188. end;
  189.  
  190. function TrmDGTreeNode.HasAsParent(Value: TrmDGTreeNode): Boolean;
  191. begin
  192.   if Value <> Nil then
  193.   begin
  194.     if Parent = nil then
  195.       Result := False
  196.     else
  197.       if Parent = Value then
  198.         Result := True
  199.       else
  200.         Result := Parent.HasAsParent(Value);
  201.   end
  202.   else
  203.     Result := True;
  204. end;
  205.  
  206. procedure TrmDGTreeNode.SetText(const S: Char);
  207. begin
  208.   FText := S;
  209. end;
  210.  
  211. procedure TrmDGTreeNode.SetData(Value: Integer);
  212. begin
  213.   FData := Value;
  214. end;
  215.  
  216. function TrmDGTreeNode.GetChildren: Boolean;
  217. begin
  218.   Result := FChildList.Count > 0;
  219. end;
  220.  
  221. function TrmDGTreeNode.GetParent: TrmDGTreeNode;
  222. begin
  223.   Result := FParent;
  224. end;
  225.  
  226. procedure TrmDGTreeNode.SetParent(Value : TrmDGTreeNode);
  227. begin
  228.   FParent := Value;
  229. end;
  230.  
  231.  
  232. function TrmDGTreeNode.GetNextSibling: TrmDGTreeNode;
  233. var
  234.   CurIdx : Integer;
  235.  
  236. begin
  237.   if Parent <> nil then
  238.   begin
  239.     CurIdx := Parent.FChildList.IndexOf(Self);
  240.     if (CurIdx + 1) < Parent.FChildList.Count then
  241.       Result := Parent.FChildList.Items[CurIdx + 1]
  242.     else
  243.       Result := nil;
  244.   end
  245.   else
  246.   begin
  247.     CurIdx := Owner.FRootNodeList.IndexOf(Self);
  248.     if (CurIdx + 1) < Owner.FRootNodeList.Count then
  249.       Result := Owner.FRootNodeList.Items[CurIdx + 1]
  250.     else
  251.       Result := nil;
  252.   end;    
  253. end;
  254.  
  255. function TrmDGTreeNode.GetPrevSibling: TrmDGTreeNode;
  256. var
  257.   CurIdx : Integer;
  258. begin
  259.   if Parent <> nil then
  260.   begin
  261.     CurIdx := Parent.FChildList.IndexOf(Self);
  262.     if (CurIdx - 1) < 0 then
  263.       Result := Parent.FChildList.Items[CurIdx - 1]
  264.     else
  265.       Result := nil;
  266.   end
  267.   else
  268.   begin
  269.     CurIdx := Owner.FRootNodeList.IndexOf(Self);
  270.     if (CurIdx - 1) < Owner.FRootNodeList.Count then
  271.       Result := Owner.FRootNodeList.Items[CurIdx - 1]
  272.     else
  273.       Result := nil;
  274.   end;
  275. end;
  276.  
  277. function TrmDGTreeNode.GetNextChild(Value: TrmDGTreeNode): TrmDGTreeNode;
  278. begin
  279.   if Value <> nil then
  280.     Result := Value.GetNextSibling
  281.   else
  282.     Result := nil;
  283. end;
  284.  
  285. function TrmDGTreeNode.GetPrevChild(Value: TrmDGTreeNode): TrmDGTreeNode;
  286. begin
  287.   if Value <> nil then
  288.     Result := Value.GetPrevSibling
  289.   else
  290.     Result := nil;
  291. end;
  292.  
  293. function TrmDGTreeNode.GetFirstChild: TrmDGTreeNode;
  294. begin
  295.   if FChildList.Count > 0 then
  296.   begin
  297.     Result := FChildList.Items[0];
  298.   end
  299.   else
  300.     Result := nil;
  301. end;
  302.  
  303. function TrmDGTreeNode.GetLastChild: TrmDGTreeNode;
  304. begin
  305.   if FChildList.Count > 0 then
  306.   begin
  307.     Result := FChildList.Items[FChildList.Count - 1]
  308.   end
  309.   else
  310.     Result := nil;
  311. end;
  312.  
  313. function TrmDGTreeNode.GetNext: TrmDGTreeNode;
  314. var
  315.   N : TrmDGTreeNode;
  316.   P : TrmDGTreeNode;
  317.  
  318. begin
  319.   if HasChildren then
  320.     N := GetFirstChild
  321.   else
  322.   begin
  323.     N := GetNextSibling;
  324.     if N = nil then
  325.     begin
  326.       P := Parent;
  327.       while P <> nil do
  328.       begin
  329.         N := P.GetNextSibling;
  330.         if N <> nil then
  331.           Break;
  332.         P := P.Parent;
  333.       end;
  334.     end;
  335.   end;
  336.   Result := N;
  337. end;
  338.  
  339. function TrmDGTreeNode.GetPrev: TrmDGTreeNode;
  340. var
  341.   Node: TrmDGTreeNode;
  342.  
  343. begin
  344.   Result := GetPrevSibling;
  345.   if Result <> nil then
  346.   begin
  347.     Node := Result;
  348.     repeat
  349.       Result := Node;
  350.       Node := Result.GetLastChild;
  351.     until Node = nil;
  352.   end
  353.   else
  354.     Result := Parent;
  355. end;
  356.  
  357. function TrmDGTreeNode.GetIndex: Integer;
  358. var
  359.   Node: TrmDGTreeNode;
  360.  
  361. begin
  362.   Result := -1;
  363.   Node := Self;
  364.   while Node <> nil do
  365.   begin
  366.     Inc(Result);
  367.     Node := Node.GetPrevSibling;
  368.   end;
  369. end;
  370.  
  371. function TrmDGTreeNode.GetItem(Index: Integer): TrmDGTreeNode;
  372. begin
  373.   Result := GetFirstChild;
  374.   while (Result <> nil) and (Index > 0) do
  375.   begin
  376.     Result := GetNextChild(Result);
  377.     Dec(Index);
  378.   end;
  379.   if Result = nil then DGTreeError('List Index Out of Bounds');
  380. end;
  381.  
  382. procedure TrmDGTreeNode.SetItem(Index: Integer; Value: TrmDGTreeNode);
  383. begin
  384.   item[Index].Assign(Value);
  385. end;
  386.  
  387. function TrmDGTreeNode.IndexOf(Value: TrmDGTreeNode): Integer;
  388. var
  389.   Node: TrmDGTreeNode;
  390. begin
  391.   Result := -1;
  392.   Node := GetFirstChild;
  393.   while (Node <> nil) do
  394.   begin
  395.     Inc(Result);
  396.     if Node = Value then Break;
  397.     Node := GetNextChild(Node);
  398.   end;
  399.   if Node = nil then
  400.     Result := -1;
  401. end;
  402.  
  403. function TrmDGTreeNode.MoveTo(Destination: TrmDGTreeNode; Mode: TNodeAttachMode) : TrmDGTreeNode;
  404. {var
  405.   AddMode : TAddMode;
  406.   node    : TrmDGTreeNode;
  407.  }
  408. begin
  409.   Result := nil;
  410. {  if (Destination = nil) or not Destination.HasAsParent(Self) then
  411.     begin
  412.       AddMode := taAdd;
  413.       if (Destination <> nil) and not (Mode in [naAddChild, naAddChildFirst]) then
  414.         Node := Destination.Parent else
  415.         Node := Destination;
  416.       case Mode of
  417.         naAdd,
  418.         naAddChild: AddMode := taAdd;
  419.         naAddFirst,
  420.         naAddChildFirst: AddMode := taAddFirst;
  421.         naInsert:
  422.           begin
  423.             Destination := Destination.GetPrevSibling;
  424.             if Destination = nil then AddMode := taAddFirst
  425.             else AddMode := taInsert;
  426.           end;
  427.       end;
  428.  
  429.       result := owner.InternalAddObject(Destination, Text, data, AddMode);
  430.       delete;
  431.     end
  432.   else
  433.     result:=self;}
  434. end;
  435.  
  436. function TrmDGTreeNode.GetCount: Integer;
  437. var
  438.   Node: TrmDGTreeNode;
  439.  
  440. begin
  441.   Result := 0;
  442.   Node := GetFirstChild;
  443.   while Node <> nil do
  444.   begin
  445.     Inc(Result);
  446.     Node := Node.GetNextChild(Node);
  447.   end;
  448. end;
  449.  
  450. function TrmDGTreeNode.GetLevel: Integer;
  451. var
  452.   Node: TrmDGTreeNode;
  453.  
  454. begin
  455.   Result := 0;
  456.   Node := Parent;
  457.   while Node <> nil do
  458.   begin
  459.     Inc(Result);
  460.     Node := Node.Parent;
  461.   end;
  462. end;
  463.  
  464. procedure TrmDGTreeNode.Delete;
  465. begin
  466.   if HasChildren then
  467.     DeleteChildren;
  468.  
  469.   TrmCustomDGTree(Owner.Owner).Delete(Self);
  470.   if Parent <> nil then
  471.   begin
  472.     Parent.FChildList.Delete(Parent.FChildList.IndexOf(Self));
  473.     Parent.FChildList.Pack;
  474.   end
  475.   else
  476.   begin
  477.     Owner.FRootNodeList.Delete(Owner.FRootNodeList.IndexOf(Self));
  478.     Owner.FRootNodeList.Pack;
  479.   end;
  480.   Free;
  481. end;
  482.  
  483. procedure TrmDGTreeNode.DeleteChildren;
  484. var
  485.   Node: TrmDGTreeNode;
  486.  
  487. begin
  488.   Node := GetFirstChild;
  489.   while Node <> nil do
  490.   begin
  491.     Node.Delete;
  492.     Node := GetFirstChild;
  493.   end;
  494. end;
  495.  
  496. procedure TrmDGTreeNode.Assign(Source: TPersistent);
  497. var
  498.   Node: TrmDGTreeNode;
  499.  
  500. begin
  501.   if Source is TrmDGTreeNode then
  502.   begin
  503.     Node := TrmDGTreeNode(Source);
  504.     Text := Node.Text;
  505.     Data := Node.Data;
  506.   end
  507.   else
  508.     inherited Assign(Source);
  509. end;
  510.  
  511. function TrmDGTreeNode.IsEqual(Node: TrmDGTreeNode): Boolean;
  512. begin
  513.   Result := (Text = Node.Text) and (Data = Node.Data);
  514. end;
  515.  
  516. procedure TrmDGTreeNode.ReadData(Stream: TStream; Info: PDGNodeInfo);
  517. var
  518.   I, Size, ItemCount: Integer;
  519.  
  520. begin
  521.   Stream.ReadBuffer(Size, SizeOf(Size));
  522.   Stream.ReadBuffer(Info^, Size);
  523.   Text := Info^.Text;
  524.   ItemCount := Info^.Count;
  525.   Data := Info^.Index;
  526.   for I := 0 to ItemCount - 1 do
  527.     Owner.AddChild(Self, #0).ReadData(Stream, Info);
  528. end;
  529.  
  530. procedure TrmDGTreeNode.WriteData(Stream: TStream; Info: PDGNodeInfo);
  531. var
  532.   I,
  533.   Size,
  534.   ItemCount: Integer;
  535.  
  536. begin
  537.   Size := SizeOf(TDGNodeInfo);
  538.   Info^.Text := Text;
  539.   ItemCount := Count;
  540.   Info^.Count := ItemCount;
  541.   Info^.Index := Data;
  542.   Stream.WriteBuffer(Size, SizeOf(Size));
  543.   Stream.WriteBuffer(Info^, Size);
  544.   for I := 0 to ItemCount - 1 do
  545.     Item[I].WriteData(Stream, Info);
  546. end;
  547.  
  548. { TrmDGTreeNodes }
  549.  
  550. constructor TrmDGTreeNodes.Create(AOwner: TrmCustomDGTree);
  551. begin
  552.   inherited Create;
  553.   FOwner := AOwner;
  554.   FRootNodeList := TList.Create;
  555. end;
  556.  
  557. destructor TrmDGTreeNodes.Destroy;
  558. begin
  559.   Clear;
  560.   FRootNodeList.Free;
  561.   inherited Destroy;
  562. end;
  563.  
  564. function TrmDGTreeNodes.GetCount: Integer;
  565. var
  566.   N : TrmDGTreeNode;
  567. begin
  568.   N := GetFirstNode;
  569.   Result := 0;
  570.   while N <> nil do
  571.   begin
  572.     Result := Result + 1;
  573.     N := N.GetNext;
  574.   end;
  575. end;
  576.  
  577. procedure TrmDGTreeNodes.Delete(Node: TrmDGTreeNode);
  578. begin
  579.   Node.Delete;
  580. end;
  581.  
  582. procedure TrmDGTreeNodes.Clear;
  583. var
  584.   N : TrmDGTreeNode;
  585.  
  586. begin
  587.   N := GetFirstNode;
  588.   While N <> nil do
  589.   begin
  590.     N.Delete;
  591.     N := GetFirstNode;
  592.   end;  
  593. end;
  594.  
  595. function TrmDGTreeNodes.AddChildFirst(Node: TrmDGTreeNode; const S: Char): TrmDGTreeNode;
  596. begin
  597.   Result := AddChildObjectFirst(Node, S, -1);
  598. end;
  599.  
  600. function TrmDGTreeNodes.AddChildObjectFirst(Node: TrmDGTreeNode; const S: Char;
  601.   Ptr: Integer): TrmDGTreeNode;
  602. begin
  603.   Result := InternalAddObject(Node, S, Ptr, taAddFirst);
  604. end;
  605.  
  606. function TrmDGTreeNodes.AddChild(Node: TrmDGTreeNode; const S: char): TrmDGTreeNode;
  607. begin
  608.   Result := AddChildObject(Node, S, -1);
  609. end;
  610.  
  611. function TrmDGTreeNodes.AddChildObject(Node: TrmDGTreeNode; const S: char;
  612.   Ptr: integer): TrmDGTreeNode;
  613. begin
  614.   Result := InternalAddObject(Node, S, Ptr, taAdd);
  615. end;
  616.  
  617. function TrmDGTreeNodes.AddFirst(Node: TrmDGTreeNode; const S: char): TrmDGTreeNode;
  618. begin
  619.   Result := AddObjectFirst(Node, S, -1);
  620. end;
  621.  
  622. function TrmDGTreeNodes.AddObjectFirst(Node: TrmDGTreeNode; const S: char;
  623.   Ptr: integer): TrmDGTreeNode;
  624. begin
  625.   if Node <> nil then Node := Node.Parent;
  626.   Result := InternalAddObject(Node, S, Ptr, taAddFirst);
  627. end;
  628.  
  629. function TrmDGTreeNodes.Add(Node: TrmDGTreeNode; const S: char): TrmDGTreeNode;
  630. begin
  631.   Result := AddObject(Node, S, -1);
  632. end;
  633.  
  634. function TrmDGTreeNodes.AddObject(Node: TrmDGTreeNode; const S: char;
  635.   Ptr: integer): TrmDGTreeNode;
  636. begin
  637.   if Node <> nil then Node := Node.Parent;
  638.   Result := InternalAddObject(Node, S, Ptr, taAdd);
  639. end;
  640.  
  641. function TrmDGTreeNodes.Insert(Node: TrmDGTreeNode; const S: char): TrmDGTreeNode;
  642. begin
  643.   Result := InsertObject(Node, S, -1);
  644. end;
  645.  
  646. function TrmDGTreeNodes.InsertObject(Node: TrmDGTreeNode; const S: char; Ptr: Integer): TrmDGTreeNode;
  647. var
  648.   Parent : TrmDGTreeNode;
  649.   AddMode : TAddMode;
  650.  
  651. begin
  652.   AddMode := taInsert;
  653.   if Node <> nil then
  654.   begin
  655.     Parent := Node.Parent;
  656.     if Parent <> nil then
  657.       Node := Node.GetPrevSibling;
  658.     if Node = nil then
  659.       AddMode := taAddFirst;
  660.   end;
  661.   Result := InternalAddObject(Node, S, Ptr, AddMode);
  662. end;
  663.  
  664.  
  665. function TrmDGTreeNodes.InternalAddObject(Node: TrmDGTreeNode; const S: char;
  666.   Ptr: integer; AddMode: TAddMode): TrmDGTreeNode;
  667. begin
  668.   Result := Owner.CreateNode;
  669.   try
  670.     case AddMode of
  671.       taAddFirst:
  672.         begin
  673.           if Node = nil then
  674.           begin
  675.             FRootNodeList.Insert(0, Result);
  676.             Result.Parent := nil;
  677.           end
  678.           else
  679.           begin
  680.             Node.FChildList.Insert(0, Result);
  681.             Result.Parent := Node;
  682.           end;
  683.           try
  684.             Result.Data := Ptr;
  685.             Result.Text := S;
  686.           except
  687.             raise;
  688.           end;
  689.         end;
  690.  
  691.       taAdd:
  692.         begin
  693.           if Node = nil then
  694.           begin
  695.             FRootNodeList.Add(Result);
  696.             Result.Parent := nil;
  697.           end
  698.           else
  699.           begin
  700.             Node.FChildList.Add(Result);
  701.             Result.Parent := Node;
  702.           end;
  703.           try
  704.             Result.Data := Ptr;
  705.             Result.Text := S;
  706.           except
  707.             raise;
  708.           end;
  709.         end;
  710.  
  711.       taInsert:
  712.         begin
  713.  
  714.  
  715.         end;
  716.     end;
  717.   except
  718.     raise;
  719.   end;
  720. end;
  721.  
  722. function TrmDGTreeNodes.GetFirstNode: TrmDGTreeNode;
  723. begin
  724.   if FRootNodeList.Count = 0 then
  725.     Result := nil
  726.   else
  727.     Result := FRootNodeList.Items[0];
  728. end;
  729.  
  730. function TrmDGTreeNodes.GetNodeFromIndex(Index: Integer): TrmDGTreeNode;
  731. var
  732.   I: Integer;
  733. begin
  734.   Result := GetFirstNode;
  735.   I := Index;
  736.   while (I <> 0) and (Result <> nil) do
  737.   begin
  738.     Result := Result.GetNext;
  739.     Dec(I);
  740.   end;
  741.   if Result = nil then
  742.     DGTreeError('Index out of range');
  743. end;
  744.  
  745. procedure TrmDGTreeNodes.SetItem(Index: Integer; Value: TrmDGTreeNode);
  746. begin
  747.   GetNodeFromIndex(Index).Assign(Value);
  748. end;
  749.  
  750. procedure TrmDGTreeNodes.Assign(Source: TPersistent);
  751. var
  752.   TreeNodes: TrmDGTreeNodes;
  753.   MemStream: TMemoryStream;
  754. begin
  755.   if Source is TrmDGTreeNodes then
  756.   begin
  757.     TreeNodes := TrmDGTreeNodes(Source);
  758.     Clear;
  759.     MemStream := TMemoryStream.Create;
  760.     try
  761.       TreeNodes.WriteData(MemStream);
  762.       MemStream.Position := 0;
  763.       ReadData(MemStream);
  764.     finally
  765.       MemStream.Free;
  766.     end;
  767.   end
  768.   else inherited Assign(Source);
  769. end;
  770.  
  771. procedure TrmDGTreeNodes.DefineProperties(Filer: TFiler);
  772.  
  773.   function WriteNodes: Boolean;
  774.   var
  775.     I: Integer;
  776.     Nodes: TrmDGTreeNodes;
  777.   begin
  778.     Nodes := TrmDGTreeNodes(Filer.Ancestor);
  779.     if Nodes = nil then
  780.       Result := Count > 0
  781.     else if Nodes.Count <> Count then
  782.       Result := True
  783.     else
  784.     begin
  785.       Result := False;
  786.       for I := 0 to Count - 1 do
  787.       begin
  788.         Result := not Item[I].IsEqual(Nodes[I]);
  789.         if Result then Break;
  790.       end
  791.     end;
  792.   end;
  793.  
  794. begin
  795.   inherited DefineProperties(Filer);
  796.   Filer.DefineBinaryProperty('Data', ReadData, WriteData, WriteNodes);
  797. end;
  798.  
  799. procedure TrmDGTreeNodes.ReadData(Stream: TStream);
  800. var
  801.   I, Count: Integer;
  802.   Info : TDGNodeInfo;
  803.  
  804. begin
  805.   Clear;
  806.   Stream.ReadBuffer(Count, SizeOf(Count));
  807.   for I := 0 to Count - 1 do
  808.     Add(nil, #0).ReadData(Stream, @Info);
  809. end;
  810.  
  811. procedure TrmDGTreeNodes.WriteData(Stream: TStream);
  812. var
  813.   I: Integer;
  814.   Node: TrmDGTreeNode;
  815.   Info : TDGNodeInfo;
  816.  
  817. begin
  818.   I := 0;
  819.   Node := GetFirstNode;
  820.   while Node <> nil do
  821.   begin
  822.     Inc(I);
  823.     Node := Node.GetNextSibling;
  824.   end;
  825.   Stream.WriteBuffer(I, SizeOf(I));
  826.   Node := GetFirstNode;
  827.   while Node <> nil do
  828.   begin
  829.     Node.WriteData(Stream, @Info);
  830.     Node := Node.GetNextSibling;
  831.   end;
  832. end;
  833.  
  834. { TrmCustomDGTree }
  835.  
  836. constructor TrmCustomDGTree.Create(AOwner: TComponent);
  837. begin
  838.   inherited Create(AOwner);
  839.   FTreeNodes := TrmDGTreeNodes.Create(Self);
  840. end;
  841.  
  842. destructor TrmCustomDGTree.Destroy;
  843. begin
  844.   Items.Free;
  845.   FMemStream.Free;
  846.   inherited Destroy;
  847. end;
  848.  
  849. procedure TrmCustomDGTree.SetrmDGTreeNodes(Value: TrmDGTreeNodes);
  850. begin
  851.   Items.Assign(Value);
  852. end;
  853.  
  854. procedure TrmCustomDGTree.Delete(Node: TrmDGTreeNode);
  855. begin
  856.   if Assigned(FOnDeletion) then
  857.     FOnDeletion(Self, Node);
  858. end;
  859.  
  860. function TrmCustomDGTree.CreateNode: TrmDGTreeNode;
  861. begin
  862.   Result := TrmDGTreeNode.Create(Items);
  863. end;
  864.  
  865. end.
  866.