ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/journaling/ibcontrols/IBTreeView.pas
(Generate patch)

Comparing:
ibx/trunk/ibcontrols/IBTreeView.pas (file contents), Revision 80 by tony, Mon Jan 1 11:31:07 2018 UTC vs.
ibx/branches/journaling/ibcontrols/IBTreeView.pas (file contents), Revision 362 by tony, Tue Dec 7 13:27:39 2021 UTC

# Line 31 | Line 31 | interface
31  
32   uses
33    Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ComCtrls,
34 <  DB, IBSQLParser, IBCustomDataSet;
34 >  DB, DBTreeView, IBSQLParser, IBCustomDataSet;
35  
36   type
37    {
# Line 41 | Line 41 | type
41      Node text can similarly be edited.
42    }
43  
44  TVariantArray = array of variant;
45
44    TIBTreeView = class;
45 <
48 <  { TIBTreeViewDatalink }
49 <
50 <  TIBTreeViewDatalink = class(TDataLink)
51 <  private
52 <    FOwner: TIBTreeView;
53 <  protected
54 <    procedure ActiveChanged; override;
55 <    procedure DataSetChanged; override;
56 <    procedure RecordChanged(Field: TField); override;
57 <    procedure UpdateData; override;
58 <  public
59 <    constructor Create(AOwner: TIBTreeView);
60 <  end;
45 >  TIBTreeNode = TDBTreeNode;
46  
47    { TIBTreeViewControlLink }
48  
# Line 71 | Line 56 | type
56      constructor Create(AOwner: TIBTreeView);
57    end;
58  
59 <  { TIBTreeNode }
75 <
76 <  TIBTreeNode = class(TTreeNode)
77 <  private
78 <    FKeyValue: variant;
79 <  public
80 <    constructor Create(AnOwner: TTreeNodes); override;
81 <    procedure DeleteAll;
82 <    property KeyValue: variant read FKeyValue;
83 <  end;
84 <
85 <  TIBTreeView = class(TCustomTreeView)
59 >  TIBTreeView = class(TDBTreeView)
60    private
61      { Private declarations }
88    FDataLink: TIBTreeViewDatalink;
62      FIBTreeViewControlLink: TIBTreeViewControlLink;
90    FHasChildField: string;
91    FKeyField: string;
92    FTextField: string;
93    FParentField: string;
94    FExpandNode: TTreeNode;
95    FNoAddNodeToDataset: boolean;
96    FRelationName: string;
97    FUpdateNode: TIBTreeNode;
98    FModifiedNode: TIBTreeNode;
99    FUpdating: boolean;
100    FLocatingNode: boolean;
101    FLastSelected: TVariantArray;
102    procedure ActiveChanged(Sender: TObject);
103    procedure AddNodes;
104    procedure DataSetChanged(Sender: TObject);
105    function GetDataSet: TDataSet;
106    function GetDataSource: TDataSource;
107    function GetRelationNameQualifier: string;
108    function GetSelectedKeyValue: variant;
109    procedure IBControlLinkChanged;
110    procedure NodeMoved(Node: TTreeNode);
111    procedure NodeUpdated(Node: TTreeNode);
112    procedure RecordChanged(Sender: TObject; Field: TField);
113    procedure SetHasChildField(AValue: string);
114    procedure SetKeyField(AValue: string);
115    procedure SetTextField(AValue: string);
116    procedure SetDataSource(AValue: TDataSource);
117    procedure SetParentField(AValue: string);
118    function ScrollToNode(Node: TIBTreeNode): boolean;
119    procedure UpdateData(Sender: TObject);
63      procedure UpdateParams(Sender: TObject; Parser: TSelectSQLParser);
64      procedure UpdateSQL(Sender: TObject; Parser: TSelectSQLParser);
65     protected
66 <    { Protected declarations }
67 <     procedure Added(Node: TTreeNode); override;
125 <     procedure Delete(Node: TTreeNode); override;
126 <     procedure Change(Node: TTreeNode); override;
127 <     function CreateNode: TTreeNode; override;
128 <     function CanEdit(Node: TTreeNode): Boolean; override;
129 <     procedure Expand(Node: TTreeNode); override;
130 <     procedure Loaded; override;
131 <     procedure NodeChanged(Node: TTreeNode; ChangeEvent: TTreeNodeChangeReason); override;
132 <     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
133 <     procedure Reinitialise;
66 >     procedure DataSourceChanged; override;
67 >     procedure RefreshDataset; override;
68    public
69      { Public declarations }
70      constructor Create(TheComponent: TComponent); override;
71      destructor Destroy; override;
138    function FindNode(KeyValuePath: TVariantArray; SelectNode: boolean): TIBTreeNode; overload;
139    function FindNode(KeyValue: variant): TIBTreeNode; overload;
140    function GetNodePath(Node: TTreeNode): TVariantArray;
141    property DataSet: TDataSet read GetDataSet;
142    property SelectedKeyValue: variant read GetSelectedKeyValue;
143  published
144    { Published declarations }
145    property Align;
146    property Anchors;
147    property AutoExpand;
148    property BorderSpacing;
149    //property BiDiMode;
150    property BackgroundColor;
151    property BorderStyle;
152    property BorderWidth;
153    property Color;
154    property Constraints;
155    property TextField: string read FTextField write SetTextField;
156    property DataSource: TDataSource read GetDataSource write SetDataSource;
157    property DefaultItemHeight;
158    property DragKind;
159    property DragCursor;
160    property DragMode;
161    property Enabled;
162    property ExpandSignColor;
163    property ExpandSignType;
164    property Font;
165    property HideSelection;
166    property HotTrack;
167    property Images;
168    property Indent;
169    property HasChildField: string read FHasChildField write SetHasChildField;
170    property KeyField: string read FKeyField write SetKeyField;
171    property MultiSelect;
172    property MultiSelectStyle;
173    //property ParentBiDiMode;
174    property ParentColor default False;
175    property ParentField: string read FParentField write SetParentField;
176    property ParentFont;
177    property ParentShowHint;
178    property PopupMenu;
179    property ReadOnly;
180    property RelationName: string read FRelationName write FRelationName;
181    property RightClickSelect;
182    property RowSelect;
183    property ScrollBars;
184    property SelectionColor;
185    property ShowButtons;
186    property ShowHint;
187    property ShowLines;
188    property ShowRoot;
189    property StateImages;
190    property TabOrder;
191    property TabStop default True;
192    property Tag;
193    property ToolTips;
194    property Visible;
195    property OnAddition;
196    property OnAdvancedCustomDraw;
197    property OnAdvancedCustomDrawItem;
198    property OnChange;
199    property OnChanging;
200    property OnClick;
201    property OnCollapsed;
202    property OnCollapsing;
203    property OnCompare;
204    property OnContextPopup;
205    property OnCreateNodeClass;
206    property OnCustomCreateItem;
207    property OnCustomDraw;
208    property OnCustomDrawItem;
209    property OnDblClick;
210    property OnDeletion;
211    property OnDragDrop;
212    property OnDragOver;
213    property OnEdited;
214    property OnEditing;
215    property OnEditingEnd;
216    //property OnEndDock;
217    property OnEndDrag;
218    property OnEnter;
219    property OnExit;
220    property OnExpanded;
221    property OnExpanding;
222    property OnGetImageIndex;
223    property OnGetSelectedIndex;
224    property OnKeyDown;
225    property OnKeyPress;
226    property OnKeyUp;
227    property OnMouseDown;
228    property OnMouseEnter;
229    property OnMouseLeave;
230    property OnMouseMove;
231    property OnMouseUp;
232    property OnNodeChanged;
233    property OnSelectionChanged;
234    property OnShowHint;
235    //property OnStartDock;
236    property OnStartDrag;
237    property OnUTF8KeyPress;
238    property Options;
239    property Items;
240    property TreeLineColor;
241    property TreeLinePenStyle;
72    end;
73  
74 <  function StrIntListToVar(s: string): TVariantArray;
75 <  function VarToStrIntList(a: TVariantArray): string;
74 > function StrIntListToVar(s: string): TVariantArray;
75 > function VarToStrIntList(a: TVariantArray): string;
76  
77   implementation
78  
79 < uses IBQuery,Variants;
79 > uses IBQuery;
80  
81   function StrIntListToVar(s: string): TVariantArray;
252 var i, idx: integer;
253    List: TStringList;
82   begin
83 <  List := TStringList.Create;
256 <  try
257 <    idx := 1;
258 <    List.Clear;
259 <    while idx <= Length(s) do
260 <       List.Add(ExtractFieldName(s,idx));
261 <
262 <    Setlength(Result,List.Count);
263 <    for i := 0 to List.Count - 1 do
264 <        Result[i] := StrToInt(List[i])
265 <  finally
266 <    List.Free
267 <  end;
83 >  Result := DBTreeView.StrIntListToVar(s);
84   end;
85  
86   function VarToStrIntList(a: TVariantArray): string;
271 var i: integer;
87   begin
88 <  for i := 0 to Length(a) - 1 do
274 <      if VarIsOrdinal(a[i]) then
275 <      begin
276 <        if i = 0 then
277 <           Result := IntToStr(a[i])
278 <        else
279 <          Result := Result + ';' + IntToStr(a[i])
280 <      end
281 <      else
282 <        raise Exception.Create('Ordinal Type Expected when converting to integer string');
88 >  Result := DBTreeView.VarToStrIntList(a);
89   end;
90  
91 +
92   { TIBTreeViewControlLink }
93  
94   constructor TIBTreeViewControlLink.Create(AOwner: TIBTreeView);
# Line 300 | Line 107 | begin
107    FOwner.UpdateSQL(self,TIBParserDataSet(Sender).Parser)
108   end;
109  
303 { TIBTreeNode }
304
305 constructor TIBTreeNode.Create(AnOwner: TTreeNodes);
306 begin
307  inherited Create(AnOwner);
308  FKeyValue := NULL;
309 end;
310
311 procedure TIBTreeNode.DeleteAll;
312 var Node, NextNode: TTreeNode;
313 begin
314    Expand(true);
315    Node := GetFirstChild;
316    while Node <> nil do
317    begin
318      NextNode := Node.GetNextSibling;
319      TIBTreeNode(Node).DeleteAll;
320      Node := NextNode;
321    end;
322    Delete
323 end;
324
325 { TIBTreeView }
326
327 procedure TIBTreeView.ActiveChanged(Sender: TObject);
328 var AtTopLevel: boolean;
329 begin
330  if (csDesigning in ComponentState) then Exit;
331  IBControlLinkChanged;
332  if assigned(DataSet) and not DataSet.Active then
333  begin
334    if not assigned(FExpandNode) and not assigned(FUpdateNode) then {must really be closing}
335      Reinitialise
336  end
337  else
338  begin
339    AtTopLevel := Items.TopLvlCount = 0;
340    AddNodes;
341    if not FLocatingNode and (Selected = nil) and (Items.TopLvlCount > 0) then
342    begin
343      if Length(FLastSelected) > 0 then
344         Selected := FindNode(FLastSelected,true)
345      else
346        Selected := Items.TopLvlItems[0];
347    end
348  end
349 end;
350
351 procedure TIBTreeView.AddNodes;
352 var Node: TTreeNode;
353    ChildCount: integer;
354 begin
355  if assigned(FExpandNode) or (Items.Count = 0) then
356  begin
357    ChildCount := 0;
358    FNoAddNodeToDataset := true;
359    try
360      DataSet.First;
361      while not DataSet.EOF do
362      begin
363        Node := Items.AddChild(FExpandNode,DataSet.FieldByName(TextField).AsString);
364        TIBTreeNode(Node).FKeyValue := DataSet.FieldByName(KeyField).AsVariant;
365        Node.HasChildren := (HasChildField = '') or (DataSet.FieldByName(HasChildField).AsInteger <> 0);
366        Inc(ChildCount);
367        DataSet.Next
368      end;
369    finally
370      FNoAddNodeToDataset := false
371    end;
372    if assigned(FExpandNode) then
373      FExpandNode.HasChildren := ChildCount > 0;
374    FExpandNode := nil
375  end
376 end;
377
378 procedure TIBTreeView.DataSetChanged(Sender: TObject);
379 begin
380 //  Reinitialise
381 end;
382
383 function TIBTreeView.GetDataSet: TDataSet;
384 begin
385  Result := FDataLink.DataSet
386 end;
387
388 function TIBTreeView.GetDataSource: TDataSource;
389 begin
390  Result := FDataLink.DataSource
391 end;
392
393 function TIBTreeView.GetRelationNameQualifier: string;
394 begin
395  if FRelationName <> '' then
396     Result := FRelationName + '.'
397  else
398    Result := ''
399 end;
400
401 function TIBTreeView.GetSelectedKeyValue: variant;
402 begin
403  Result := NULL;
404  if assigned(Selected) and (Selected is TIBTreeNode) then
405     Result := TIBTreeNode(Selected).KeyValue
406 end;
407
408 procedure TIBTreeView.NodeMoved(Node: TTreeNode);
409 begin
410  {Need to update Parent}
411  if ScrollToNode(TIBTreeNode(Node))  then
412  begin
413      FDataLink.Edit;
414      FModifiedNode := TIBTreeNode(Node)
415  end;
416 end;
417
418 procedure TIBTreeView.NodeUpdated(Node: TTreeNode);
419 begin
420  {Need to Update List Field}
421  if ScrollToNode(TIBTreeNode(Node)) then
422  begin
423    FDataLink.Edit;
424    FModifiedNode := TIBTreeNode(Node);
425    FDataLink.UpdateRecord
426  end;
427 end;
428
429 procedure TIBTreeView.RecordChanged(Sender: TObject; Field: TField);
430 var Node: TIBTreeNode;
431    Destination: TIBTreeNode;
432 begin
433  if DataSet.State = dsInsert then Exit;
434
435  if assigned(Field) and (Field.FieldName = TextField) then
436  begin
437    Node := FindNode(DataSet.FieldByName(KeyField).AsVariant);
438    if assigned(Node) then
439    begin
440      FUpdating := true;
441      try
442        Node.Text := Field.Text
443      finally
444        FUpdating := false
445      end;
446    end;
447  end
448  else
449  if assigned(Field) and (Field.FieldName = ParentField) then
450  begin
451    Node := FindNode(DataSet.FieldByName(KeyField).AsVariant);
452    if assigned(Node)  then
453    begin
454      if DataSet.FieldByName(ParentField).IsNull then
455         Destination := nil
456      else
457        Destination := FindNode(DataSet.FieldByName(ParentField).AsVariant);
458
459      if (Destination = nil) or (Destination = Node.Parent) then Exit;
460
461      FUpdating := true;
462      try
463        Node.MoveTo(Destination,naAddChild);
464      finally
465        FUpdating := false
466      end;
467    end;
468  end
469 end;
470
471 procedure TIBTreeView.SetHasChildField(AValue: string);
472 begin
473  if FHasChildField = AValue then Exit;
474  FHasChildField := AValue;
475  Reinitialise
476 end;
477
478 procedure TIBTreeView.SetKeyField(AValue: string);
479 begin
480  if FKeyField = AValue then Exit;
481  FKeyField := AValue;
482  Reinitialise
483 end;
484
485 procedure TIBTreeView.SetTextField(AValue: string);
486 begin
487  if FTextField = AValue then Exit;
488  FTextField := AValue;
489  Reinitialise
490 end;
491
492 procedure TIBTreeView.SetDataSource(AValue: TDataSource);
493 begin
494  FDataLink.DataSource := AValue;
495  IBControlLinkChanged;
496 end;
497
498 procedure TIBTreeView.SetParentField(AValue: string);
499 begin
500  if FParentField = AValue then Exit;
501  FParentField := AValue;
502  Reinitialise
503 end;
504
505 function TIBTreeView.ScrollToNode(Node: TIBTreeNode): boolean;
506 begin
507  Result :=  assigned(DataSet) and DataSet.Active and assigned(Node) and not varIsNull(Node.KeyValue);
508  if Result then
509  begin
510    if DataSet.Active and (DataSet.RecordCount > 0)
511         and DataSet.Locate(KeyField,Node.KeyValue,[]) then Exit;
512
513    FUpdateNode := Node;
514    try
515      DataSet.Active := false;
516      DataSet.Active := true;
517    finally
518      FUpdateNode := nil
519    end;
520    Result := DataSet.FieldByName(KeyField).AsVariant = Node.KeyValue
521  end;
522 end;
523
524 procedure TIBTreeView.UpdateData(Sender: TObject);
525 begin
526  if assigned(FModifiedNode) then
527  begin
528    DataSet.FieldByName(TextField).AsString := FModifiedNode.Text;
529    if FModifiedNode.Parent = nil then
530      DataSet.FieldByName(ParentField).Clear
531    else
532      DataSet.FieldByName(ParentField).AsVariant := TIBTreeNode(FModifiedNode.Parent).KeyValue;
533    FModifiedNode := nil
534  end
535 end;
110  
111   procedure TIBTreeView.UpdateParams(Sender: TObject; Parser: TSelectSQLParser);
112   begin
# Line 551 | Line 125 | begin
125    begin
126      if DataSource.DataSet is TIBQuery then
127        TIBQuery(DataSource.DataSet).ParamByName('IBX_PARENT_VALUE').Value :=
128 <        TIBTreeNode(FExpandNode).KeyValue
128 >        TDBTreeNode(FExpandNode).KeyValue
129      else
130      if DataSource.DataSet is TIBDataSet then
131        TIBDataSet(DataSource.DataSet).ParamByName('IBX_PARENT_VALUE').Value :=
132 <        TIBTreeNode(FExpandNode).KeyValue
132 >        TDBTreeNode(FExpandNode).KeyValue
133    end;
134   end;
135  
136   procedure TIBTreeView.UpdateSQL(Sender: TObject; Parser: TSelectSQLParser);
137   begin
138      if not assigned(FExpandNode) and assigned(FUpdateNode)  then {Scrolling dataset}
139 <      Parser.Add2WhereClause(GetRelationNameQualifier + '"' + FKeyField + '" = :IBX_KEY_VALUE')
139 >      Parser.Add2WhereClause(GetRelationNameQualifier + '"' + KeyField + '" = :IBX_KEY_VALUE')
140      else
141      if (Items.Count = 0) then
142        {Need to Load Root Nodes}
143 <      Parser.Add2WhereClause(GetRelationNameQualifier + '"' + FParentField + '" is null')
143 >      Parser.Add2WhereClause(GetRelationNameQualifier + '"' + ParentField + '" is null')
144      else
145      if assigned(FExpandNode) then
146 <      Parser.Add2WhereClause(GetRelationNameQualifier + '"' + FParentField + '" = :IBX_PARENT_VALUE');
147 < end;
148 <
149 < procedure TIBTreeView.Added(Node: TTreeNode);
576 < begin
577 <  if assigned(DataSet) and DataSet.Active and not FNoAddNodeToDataset then
578 <  begin
579 <    DataSet.Append;
580 <    TIBTreeNode(Node).FKeyValue := DataSet.FieldByName(KeyField).AsVariant;
581 <    if (Node.Text = '') and not DataSet.FieldByName(TextField).IsNull then
582 <       Node.Text := DataSet.FieldByName(TextField).AsString;
583 <    FModifiedNode := TIBTreeNode(Node);
584 <    FDataLink.UpdateRecord
585 <  end;
586 <  inherited Added(Node);
587 < end;
588 <
589 < procedure TIBTreeView.Delete(Node: TTreeNode);
590 < begin
591 <  if not (tvsUpdating in States) {TreeNodes being cleared}
592 <     and not (tvsManualNotify in States) {Tree Collapse with node delete}
593 <     and ScrollToNode(TIBTreeNode(Node)) then
594 <     DataSet.Delete;
595 <  inherited Delete(Node);
596 < end;
597 <
598 < procedure TIBTreeView.Change(Node: TTreeNode);
599 < begin
600 <  inherited Change(Node);
601 <  ScrollToNode(TIBTreeNode(Node));
602 < end;
603 <
604 < function TIBTreeView.CreateNode: TTreeNode;
605 < var
606 <  NewNodeClass: TTreeNodeClass;
607 < begin
608 <  Result := nil;
609 <  if Assigned(OnCustomCreateItem) then
610 <    OnCustomCreateItem(Self, Result);
611 <  if Result = nil then
612 <  begin
613 <    NewNodeClass:=TIBTreeNode;
614 <    if Assigned(OnCreateNodeClass) then
615 <      OnCreateNodeClass(Self,NewNodeClass);
616 <    Result := NewNodeClass.Create(Items);
617 <  end;
618 < end;
619 <
620 < function TIBTreeView.CanEdit(Node: TTreeNode): Boolean;
621 < begin
622 <  Result := inherited CanEdit(Node)
623 <              and assigned(DataSet) and not DataSet.FieldByName(TextField).ReadOnly
624 < end;
625 <
626 < procedure TIBTreeView.Expand(Node: TTreeNode);
627 < begin
628 <  inherited Expand(Node);
629 <  if Node.HasChildren and assigned(DataSet) and (Node.GetFirstChild = nil) then
630 <  begin
631 <    FExpandNode := Node;
632 <    DataSet.Active := false;
633 <    DataSet.Active := true;
634 <    if assigned(Selected) then
635 <      ScrollToNode(TIBTreeNode(Selected))
636 <  end;
637 < end;
638 <
639 < procedure TIBTreeView.IBControlLinkChanged;
640 < begin
641 <  if assigned(DataSource) and (DataSource.DataSet <> nil) and (DataSource.DataSet is TIBParserDataset) then
642 <    FIBTreeViewControllink.IBDataSet := TIBCustomDataSet(DataSource.DataSet)
643 <  else
644 <    FIBTreeViewControllink.IBDataSet := nil;
645 < end;
646 <
647 < procedure TIBTreeView.Loaded;
648 < begin
649 <  inherited Loaded;
650 <  IBControlLinkChanged;
651 <  Reinitialise
652 < end;
653 <
654 < procedure TIBTreeView.NodeChanged(Node: TTreeNode;
655 <  ChangeEvent: TTreeNodeChangeReason);
656 < begin
657 <  inherited NodeChanged(Node, ChangeEvent);
658 <  if not FNoAddNodeToDataset and not FUpdating then
659 <  case ChangeEvent of
660 <  ncTextChanged:
661 <    NodeUpdated(Node);
662 <  ncParentChanged:
663 <    NodeMoved(Node);
664 <  end;
146 >    begin
147 >      Parser.Add2WhereClause(GetRelationNameQualifier + '"' + ParentField + '" = :IBX_PARENT_VALUE');
148 >      Parser.Add2WhereClause(GetRelationNameQualifier + '"' + KeyField + '" = :IBX_PARENT_VALUE',true);
149 >    end;
150   end;
151  
152 < procedure TIBTreeView.Notification(AComponent: TComponent; Operation: TOperation
668 <  );
152 > procedure TIBTreeView.DataSourceChanged;
153   begin
154 <  inherited Notification(AComponent, Operation);
155 <  if (Operation = opRemove) and
156 <     (FDataLink <> nil) and (AComponent = DataSource) then
157 <     DataSource := nil;
154 >    if assigned(DataSource) and (DataSource.DataSet <> nil) and (DataSource.DataSet is TIBParserDataset) then
155 >      FIBTreeViewControllink.IBDataSet := TIBCustomDataSet(DataSource.DataSet)
156 >    else
157 >      FIBTreeViewControllink.IBDataSet := nil;
158   end;
159  
160 < procedure TIBTreeView.Reinitialise;
160 > procedure TIBTreeView.RefreshDataset;
161   begin
162 <  if [csDesigning,csLoading] * ComponentState <> [] then Exit;
163 <  FLastSelected := GetNodePath(Selected);
680 <  Items.Clear;
162 >  DataSet.Active := false;
163 >  DataSet.Active := true;
164   end;
165  
166   constructor TIBTreeView.Create(TheComponent: TComponent);
167   begin
168    inherited Create(TheComponent);
686  FDataLink := TIBTreeViewDatalink.Create(self);
169    FIBTreeViewControlLink := TIBTreeViewControlLink.Create(self);
170   end;
171  
172   destructor TIBTreeView.Destroy;
173   begin
692  if assigned(FDataLink) then FDataLink.Free;
174    if assigned(FIBTreeViewControlLink) then FIBTreeViewControlLink.Free;
175    inherited Destroy;
176   end;
177  
697 function TIBTreeView.FindNode(KeyValuePath: TVariantArray; SelectNode: boolean
698  ): TIBTreeNode;
699 var Node: TTreeNode;
700    i,j: integer;
701 begin
702  Result := nil;
703  if Length(KeyValuePath) = 0 then Exit;
704
705  FLocatingNode := true;
706  try
707   for j := 0 to Items.TopLvlCount - 1 do
708   begin
709    Node := Items.TopLvlItems[j];
710    i := 0;
711    Node.Expand(false);
712    while assigned(Node)  do
713    begin
714      if not VarIsNull(TIBTreeNode(Node).KeyValue) and
715                        (TIBTreeNode(Node).KeyValue = KeyValuePath[i]) then
716      begin
717        Inc(i);
718        if i = Length(KeyValuePath) then
719        begin
720          Result := TIBTreeNode(Node);
721          if SelectNode then
722             Selected := Node;
723          Exit
724        end
725        else
726        begin
727          Node.Expand(false);
728          Node := Node.GetFirstChild;
729        end
730      end
731      else
732        Node := Node.GetNextSibling
733    end
734   end
735  finally
736    FLocatingNode := false
737  end
738 end;
739
740 function TIBTreeView.FindNode(KeyValue: variant): TIBTreeNode;
741 var i: integer;
742 begin
743  Result := nil;
744  if (Selected <> nil) and (TIBTreeNode(Selected).KeyValue = KeyValue) then
745     Result := TIBTreeNode(Selected)
746  else
747  {Find it the hard way}
748  begin
749    FullExpand;
750    for i := 0 to Items.Count -1 do
751      if TIBTreeNode(Items[i]).KeyValue = KeyValue then
752      begin
753        Result := TIBTreeNode(Items[i])
754      end;
755  end;
756 end;
757
758 function TIBTreeView.GetNodePath(Node: TTreeNode): TVariantArray;
759 var aParent: TTreeNode;
760    i: integer;
761 begin
762  if not assigned(Node) or not (Node is TIBTreeNode) then
763     SetLength(Result,0)
764  else
765  begin
766    {Count length of Path}
767    i := 1;
768    aParent := Node.Parent;
769    while (aParent <> nil) do
770    begin
771        Inc(i);
772        aParent := aParent.Parent
773    end;
774
775    {Save Path}
776    Setlength(Result,i);
777    while i > 0 do
778    begin
779      Dec(i);
780      Result[i] := TIBTreeNode(Node).KeyValue;
781      Node := Node.Parent
782    end;
783  end;
784 end;
785
786 { TIBTreeViewDatalink }
787
788 procedure TIBTreeViewDatalink.ActiveChanged;
789 begin
790  FOwner.ActiveChanged(self)
791 end;
792
793 procedure TIBTreeViewDatalink.DataSetChanged;
794 begin
795  FOwner.DataSetChanged(self)
796 end;
797
798 procedure TIBTreeViewDatalink.RecordChanged(Field: TField);
799 begin
800  FOwner.RecordChanged(self,Field);
801 end;
802
803 procedure TIBTreeViewDatalink.UpdateData;
804 begin
805  FOwner.UpdateData(self)
806 end;
807
808 constructor TIBTreeViewDatalink.Create(AOwner: TIBTreeView);
809 begin
810  inherited Create;
811  FOwner := AOwner
812 end;
813
178   end.

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines