ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/journaling/ibcontrols/IBTreeView.pas
Revision: 21
Committed: Thu Feb 26 10:33:34 2015 UTC (9 years, 9 months ago) by tony
Content type: text/x-pascal
Original Path: ibx/trunk/ibcontrols/IBTreeView.pas
File size: 20998 byte(s)
Log Message:
Committing updates for Release R1-2-0

File Contents

# User Rev Content
1 tony 21 (*
2     * IBX For Lazarus (Firebird Express)
3     *
4     * The contents of this file are subject to the Initial Developer's
5     * Public License Version 1.0 (the "License"); you may not use this
6     * file except in compliance with the License. You may obtain a copy
7     * of the License here:
8     *
9     * http://www.firebirdsql.org/index.php?op=doc&id=idpl
10     *
11     * Software distributed under the License is distributed on an "AS
12     * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13     * implied. See the License for the specific language governing rights
14     * and limitations under the License.
15     *
16     * The Initial Developer of the Original Code is Tony Whyman.
17     *
18     * The Original Code is (C) 2011 Tony Whyman, MWA Software
19     * (http://www.mwasoftware.co.uk).
20     *
21     * All Rights Reserved.
22     *
23     * Contributor(s): ______________________________________.
24     *
25     *)
26     unit IBTreeView;
27    
28     {$mode objfpc}{$H+}
29    
30     interface
31    
32     uses
33     Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ComCtrls,
34     DB, IBSQLParser;
35    
36     type
37     {
38     TIBTreeView is intended to be a data aware descendent of TCustomTreeView and used to display
39     hierarchically structured data in a natural manner. Nodes can be deleted, moved
40     and added to the tree and each change is reflected in the underlying dataset. The
41     Node text can similarly be edited.
42     }
43    
44     TVariantArray = array of variant;
45    
46     TIBTreeView = class;
47    
48     { TIBTreeViewDatalink }
49    
50     TIBTreeViewDatalink = class(TDataLink)
51     private
52     FOwner: TIBTreeView;
53     protected
54     procedure ActiveChanged; override;
55     procedure DataEvent(Event: TDataEvent; Info: Ptrint); override;
56     procedure DataSetChanged; override;
57     procedure RecordChanged(Field: TField); override;
58     procedure UpdateData; override;
59     public
60     constructor Create(AOwner: TIBTreeView);
61     end;
62    
63     { TIBTreeNode }
64    
65     TIBTreeNode = class(TTreeNode)
66     private
67     FKeyValue: variant;
68     public
69     procedure DeleteAll;
70     property KeyValue: variant read FKeyValue;
71     end;
72    
73     TIBTreeView = class(TCustomTreeView)
74     private
75     { Private declarations }
76     FDataLink: TIBTreeViewDatalink;
77     FHasChildField: string;
78     FKeyField: string;
79     FTextField: string;
80     FParentField: string;
81     FExpandNode: TTreeNode;
82     FNoAddNodeToDataset: boolean;
83     FRelationName: string;
84     FUpdateNode: TIBTreeNode;
85     FModifiedNode: TIBTreeNode;
86     FUpdating: boolean;
87     FLocatingNode: boolean;
88     FLastSelected: TVariantArray;
89     procedure ActiveChanged(Sender: TObject);
90     procedure AddNodes;
91     procedure DataSetChanged(Sender: TObject);
92     function GetDataSet: TDataSet;
93     function GetDataSource: TDataSource;
94     function GetRelationNameQualifier: string;
95     function GetSelectedKeyValue: variant;
96     procedure NodeMoved(Node: TTreeNode);
97     procedure NodeUpdated(Node: TTreeNode);
98     procedure RecordChanged(Sender: TObject; Field: TField);
99     procedure SetHasChildField(AValue: string);
100     procedure SetKeyField(AValue: string);
101     procedure SetTextField(AValue: string);
102     procedure SetDataSource(AValue: TDataSource);
103     procedure SetParentField(AValue: string);
104     function ScrollToNode(Node: TIBTreeNode): boolean;
105     procedure UpdateData(Sender: TObject);
106     procedure UpdateParams(Sender: TObject; Parser: TSelectSQLParser);
107     procedure UpdateSQL(Sender: TObject; Parser: TSelectSQLParser);
108     protected
109     { Protected declarations }
110     procedure Added(Node: TTreeNode); override;
111     procedure Delete(Node: TTreeNode); override;
112     procedure Change(Node: TTreeNode); override;
113     function CreateNode: TTreeNode; override;
114     function CanEdit(Node: TTreeNode): Boolean; override;
115     procedure Expand(Node: TTreeNode); override;
116     procedure Loaded; override;
117     procedure NodeChanged(Node: TTreeNode; ChangeEvent: TTreeNodeChangeReason); override;
118     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
119     procedure Reinitialise;
120     public
121     { Public declarations }
122     constructor Create(TheComponent: TComponent); override;
123     destructor Destroy; override;
124     function FindNode(KeyValuePath: array of variant; SelectNode: boolean): TIBTreeNode; overload;
125     function FindNode(KeyValue: variant): TIBTreeNode; overload;
126     function GetNodePath(Node: TTreeNode): TVariantArray;
127     property DataSet: TDataSet read GetDataSet;
128     property SelectedKeyValue: variant read GetSelectedKeyValue;
129     published
130     { Published declarations }
131     property Align;
132     property Anchors;
133     property AutoExpand;
134     property BorderSpacing;
135     //property BiDiMode;
136     property BackgroundColor;
137     property BorderStyle;
138     property BorderWidth;
139     property Color;
140     property Constraints;
141     property TextField: string read FTextField write SetTextField;
142     property DataSource: TDataSource read GetDataSource write SetDataSource;
143     property DefaultItemHeight;
144     property DragKind;
145     property DragCursor;
146     property DragMode;
147     property Enabled;
148     property ExpandSignColor;
149     property ExpandSignType;
150     property Font;
151     property HideSelection;
152     property HotTrack;
153     property Images;
154     property Indent;
155     property HasChildField: string read FHasChildField write SetHasChildField;
156     property KeyField: string read FKeyField write SetKeyField;
157     property MultiSelect;
158     property MultiSelectStyle;
159     //property ParentBiDiMode;
160     property ParentColor default False;
161     property ParentField: string read FParentField write SetParentField;
162     property ParentFont;
163     property ParentShowHint;
164     property PopupMenu;
165     property ReadOnly;
166     property RelationName: string read FRelationName write FRelationName;
167     property RightClickSelect;
168     property RowSelect;
169     property ScrollBars;
170     property SelectionColor;
171     property ShowButtons;
172     property ShowHint;
173     property ShowLines;
174     property ShowRoot;
175     property StateImages;
176     property TabOrder;
177     property TabStop default True;
178     property Tag;
179     property ToolTips;
180     property Visible;
181     property OnAddition;
182     property OnAdvancedCustomDraw;
183     property OnAdvancedCustomDrawItem;
184     property OnChange;
185     property OnChanging;
186     property OnClick;
187     property OnCollapsed;
188     property OnCollapsing;
189     property OnCompare;
190     property OnContextPopup;
191     property OnCreateNodeClass;
192     property OnCustomCreateItem;
193     property OnCustomDraw;
194     property OnCustomDrawItem;
195     property OnDblClick;
196     property OnDeletion;
197     property OnDragDrop;
198     property OnDragOver;
199     property OnEdited;
200     property OnEditing;
201     property OnEditingEnd;
202     //property OnEndDock;
203     property OnEndDrag;
204     property OnEnter;
205     property OnExit;
206     property OnExpanded;
207     property OnExpanding;
208     property OnGetImageIndex;
209     property OnGetSelectedIndex;
210     property OnKeyDown;
211     property OnKeyPress;
212     property OnKeyUp;
213     property OnMouseDown;
214     property OnMouseEnter;
215     property OnMouseLeave;
216     property OnMouseMove;
217     property OnMouseUp;
218     property OnNodeChanged;
219     property OnSelectionChanged;
220     property OnShowHint;
221     //property OnStartDock;
222     property OnStartDrag;
223     property OnUTF8KeyPress;
224     property Options;
225     property Items;
226     property TreeLineColor;
227     property TreeLinePenStyle;
228     end;
229    
230     function StrIntListToVar(s: string): TVariantArray;
231     function VarToStrIntList(a: TVariantArray): string;
232    
233     implementation
234    
235     uses IBQuery,IBCustomDataSet, Variants;
236    
237     function StrIntListToVar(s: string): TVariantArray;
238     var i, idx: integer;
239     List: TStringList;
240     begin
241     List := TStringList.Create;
242     try
243     idx := 1;
244     List.Clear;
245     while idx <= Length(s) do
246     List.Add(ExtractFieldName(s,idx));
247    
248     Setlength(Result,List.Count);
249     for i := 0 to List.Count - 1 do
250     Result[i] := StrToInt(List[i])
251     finally
252     List.Free
253     end;
254     end;
255    
256     function VarToStrIntList(a: TVariantArray): string;
257     var i: integer;
258     begin
259     for i := 0 to Length(a) - 1 do
260     if VarIsOrdinal(a[i]) then
261     begin
262     if i = 0 then
263     Result := IntToStr(a[i])
264     else
265     Result := Result + ';' + IntToStr(a[i])
266     end
267     else
268     raise Exception.Create('Ordinal Type Expected when converting to integer string');
269     end;
270    
271     { TIBTreeNode }
272    
273     procedure TIBTreeNode.DeleteAll;
274     var Node, NextNode: TTreeNode;
275     begin
276     Expand(true);
277     Node := GetFirstChild;
278     while Node <> nil do
279     begin
280     NextNode := Node.GetNextSibling;
281     TIBTreeNode(Node).DeleteAll;
282     Node := NextNode;
283     end;
284     Delete
285     end;
286    
287     { TIBTreeView }
288    
289     procedure TIBTreeView.ActiveChanged(Sender: TObject);
290     var AtTopLevel: boolean;
291     begin
292     if (csDesigning in ComponentState) then Exit;
293     if assigned(DataSet) and not DataSet.Active then
294     begin
295     if not assigned(FExpandNode) and not assigned(FUpdateNode) then {must really be closing}
296     Reinitialise
297     end
298     else
299     begin
300     AtTopLevel := Items.TopLvlCount = 0;
301     AddNodes;
302     if not FLocatingNode and (Selected = nil) and (Items.TopLvlCount > 0) then
303     begin
304     if Length(FLastSelected) > 0 then
305     Selected := FindNode(FLastSelected,true)
306     else
307     Selected := Items.TopLvlItems[0];
308     end
309     end
310     end;
311    
312     procedure TIBTreeView.AddNodes;
313     var Node: TTreeNode;
314     ChildCount: integer;
315     begin
316     if assigned(FExpandNode) or (Items.Count = 0) then
317     begin
318     ChildCount := 0;
319     FNoAddNodeToDataset := true;
320     try
321     DataSet.First;
322     while not DataSet.EOF do
323     begin
324     Node := Items.AddChild(FExpandNode,DataSet.FieldByName(TextField).AsString);
325     TIBTreeNode(Node).FKeyValue := DataSet.FieldByName(KeyField).AsVariant;
326     Node.HasChildren := (HasChildField = '') or (DataSet.FieldByName(HasChildField).AsInteger <> 0);
327     Inc(ChildCount);
328     DataSet.Next
329     end;
330     finally
331     FNoAddNodeToDataset := false
332     end;
333     if assigned(FExpandNode) then
334     FExpandNode.HasChildren := ChildCount > 0;
335     FExpandNode := nil
336     end
337     end;
338    
339     procedure TIBTreeView.DataSetChanged(Sender: TObject);
340     begin
341     // Reinitialise
342     end;
343    
344     function TIBTreeView.GetDataSet: TDataSet;
345     begin
346     Result := FDataLink.DataSet
347     end;
348    
349     function TIBTreeView.GetDataSource: TDataSource;
350     begin
351     Result := FDataLink.DataSource
352     end;
353    
354     function TIBTreeView.GetRelationNameQualifier: string;
355     begin
356     if FRelationName <> '' then
357     Result := FRelationName + '.'
358     else
359     Result := ''
360     end;
361    
362     function TIBTreeView.GetSelectedKeyValue: variant;
363     begin
364     Result := NULL;
365     if assigned(Selected) and (Selected is TIBTreeNode) then
366     Result := TIBTreeNode(Selected).KeyValue
367     end;
368    
369     procedure TIBTreeView.NodeMoved(Node: TTreeNode);
370     begin
371     {Need to update Parent}
372     if ScrollToNode(TIBTreeNode(Node)) then
373     begin
374     FDataLink.Edit;
375     FModifiedNode := TIBTreeNode(Node)
376     end;
377     end;
378    
379     procedure TIBTreeView.NodeUpdated(Node: TTreeNode);
380     begin
381     {Need to Update List Field}
382     if ScrollToNode(TIBTreeNode(Node)) then
383     begin
384     FDataLink.Edit;
385     FModifiedNode := TIBTreeNode(Node);
386     FDataLink.UpdateRecord
387     end;
388     end;
389    
390     procedure TIBTreeView.RecordChanged(Sender: TObject; Field: TField);
391     var Node: TIBTreeNode;
392     Destination: TIBTreeNode;
393     begin
394     if assigned(Field) and (Field.FieldName = TextField) then
395     begin
396     Node := FindNode(DataSet.FieldByName(KeyField).AsVariant);
397     if assigned(Node) then
398     begin
399     FUpdating := true;
400     try
401     Node.Text := Field.Text
402     finally
403     FUpdating := false
404     end;
405     end;
406     end
407     else
408     if assigned(Field) and (Field.FieldName = ParentField) then
409     begin
410     Node := FindNode(DataSet.FieldByName(KeyField).AsVariant);
411     if assigned(Node) then
412     begin
413     if DataSet.FieldByName(ParentField).IsNull then
414     Destination := nil
415     else
416     Destination := FindNode(DataSet.FieldByName(ParentField).AsVariant);
417    
418     if Destination = Node.Parent then Exit;
419    
420     FUpdating := true;
421     try
422     Node.MoveTo(Destination,naAddChild);
423     finally
424     FUpdating := false
425     end;
426     end;
427     end
428     end;
429    
430     procedure TIBTreeView.SetHasChildField(AValue: string);
431     begin
432     if FHasChildField = AValue then Exit;
433     FHasChildField := AValue;
434     Reinitialise
435     end;
436    
437     procedure TIBTreeView.SetKeyField(AValue: string);
438     begin
439     if FKeyField = AValue then Exit;
440     FKeyField := AValue;
441     Reinitialise
442     end;
443    
444     procedure TIBTreeView.SetTextField(AValue: string);
445     begin
446     if FTextField = AValue then Exit;
447     FTextField := AValue;
448     Reinitialise
449     end;
450    
451     procedure TIBTreeView.SetDataSource(AValue: TDataSource);
452     begin
453     FDataLink.DataSource := AValue
454     end;
455    
456     procedure TIBTreeView.SetParentField(AValue: string);
457     begin
458     if FParentField = AValue then Exit;
459     FParentField := AValue;
460     Reinitialise
461     end;
462    
463     function TIBTreeView.ScrollToNode(Node: TIBTreeNode): boolean;
464     begin
465     Result := assigned(DataSet) and DataSet.Active and assigned(Node) and not varIsNull(Node.KeyValue);
466     if Result then
467     begin
468     if DataSet.Active and (DataSet.RecordCount > 0)
469     and (Node.KeyValue = DataSet.FieldByName(KeyField).AsVariant) then Exit;
470    
471     FUpdateNode := Node;
472     try
473     DataSet.Active := false;
474     DataSet.Active := true;
475     finally
476     FUpdateNode := nil
477     end;
478     Result := DataSet.FieldByName(KeyField).AsVariant = Node.KeyValue
479     end;
480     end;
481    
482     procedure TIBTreeView.UpdateData(Sender: TObject);
483     begin
484     if assigned(FModifiedNode) then
485     begin
486     DataSet.FieldByName(TextField).AsString := FModifiedNode.Text;
487     if FModifiedNode.Parent = nil then
488     DataSet.FieldByName(ParentField).Clear
489     else
490     DataSet.FieldByName(ParentField).AsVariant := TIBTreeNode(FModifiedNode.Parent).KeyValue;
491     FModifiedNode := nil
492     end
493     end;
494    
495     procedure TIBTreeView.UpdateParams(Sender: TObject; Parser: TSelectSQLParser);
496     begin
497     if not assigned(FExpandNode) and assigned(FUpdateNode) then {Scrolling dataset}
498     begin
499     if (Sender as TDataLink).DataSet is TIBQuery then
500     TIBQuery((Sender as TDataLink).DataSet).ParamByName('IBX_KEY_VALUE').Value :=
501     FUpdateNode.KeyValue
502     else
503     if (Sender as TDataLink).DataSet is TIBDataSet then
504     TIBDataSet((Sender as TDataLink).DataSet).ParamByName('IBX_KEY_VALUE').Value :=
505     FUpdateNode.KeyValue
506     end
507     else
508     if assigned(FExpandNode) then
509     begin
510     if (Sender as TDataLink).DataSet is TIBQuery then
511     TIBQuery((Sender as TDataLink).DataSet).ParamByName('IBX_PARENT_VALUE').Value :=
512     TIBTreeNode(FExpandNode).KeyValue
513     else
514     if (Sender as TDataLink).DataSet is TIBDataSet then
515     TIBDataSet((Sender as TDataLink).DataSet).ParamByName('IBX_PARENT_VALUE').Value :=
516     TIBTreeNode(FExpandNode).KeyValue
517     end;
518     end;
519    
520     procedure TIBTreeView.UpdateSQL(Sender: TObject; Parser: TSelectSQLParser);
521     begin
522     if not assigned(FExpandNode) and assigned(FUpdateNode) then {Scrolling dataset}
523     Parser.Add2WhereClause(GetRelationNameQualifier + '"' + FKeyField + '" = :IBX_KEY_VALUE')
524     else
525     if (Items.Count = 0) then
526     {Need to Load Root Nodes}
527     Parser.Add2WhereClause(GetRelationNameQualifier + '"' + FParentField + '" is null')
528     else
529     if assigned(FExpandNode) then
530     Parser.Add2WhereClause(GetRelationNameQualifier + '"' + FParentField + '" = :IBX_PARENT_VALUE');
531     end;
532    
533     procedure TIBTreeView.Added(Node: TTreeNode);
534     begin
535     if assigned(DataSet) and DataSet.Active and not FNoAddNodeToDataset then
536     begin
537     DataSet.Append;
538     TIBTreeNode(Node).FKeyValue := DataSet.FieldByName(KeyField).AsVariant;
539     if (Node.Text = '') and not DataSet.FieldByName(TextField).IsNull then
540     Node.Text := DataSet.FieldByName(TextField).AsString;
541     FModifiedNode := TIBTreeNode(Node);
542     FDataLink.UpdateRecord
543     end;
544     inherited Added(Node);
545     end;
546    
547     procedure TIBTreeView.Delete(Node: TTreeNode);
548     begin
549     if not (tvsUpdating in States) {TreeNodes being cleared}
550     and not (tvsManualNotify in States) {Tree Collapse with node delete}
551     and ScrollToNode(TIBTreeNode(Node)) then
552     DataSet.Delete;
553     inherited Delete(Node);
554     end;
555    
556     procedure TIBTreeView.Change(Node: TTreeNode);
557     begin
558     inherited Change(Node);
559     ScrollToNode(TIBTreeNode(Node));
560     end;
561    
562     function TIBTreeView.CreateNode: TTreeNode;
563     var
564     NewNodeClass: TTreeNodeClass;
565     begin
566     Result := nil;
567     if Assigned(OnCustomCreateItem) then
568     OnCustomCreateItem(Self, Result);
569     if Result = nil then
570     begin
571     NewNodeClass:=TIBTreeNode;
572     if Assigned(OnCreateNodeClass) then
573     OnCreateNodeClass(Self,NewNodeClass);
574     Result := NewNodeClass.Create(Items);
575     end;
576     end;
577    
578     function TIBTreeView.CanEdit(Node: TTreeNode): Boolean;
579     begin
580     Result := inherited CanEdit(Node)
581     and assigned(DataSet) and not DataSet.FieldByName(TextField).ReadOnly
582     end;
583    
584     procedure TIBTreeView.Expand(Node: TTreeNode);
585     begin
586     inherited Expand(Node);
587     if Node.HasChildren and assigned(DataSet) and (Node.GetFirstChild = nil) then
588     begin
589     FExpandNode := Node;
590     DataSet.Active := false;
591     DataSet.Active := true;
592     if assigned(Selected) then
593     ScrollToNode(TIBTreeNode(Selected))
594     end;
595     end;
596    
597     procedure TIBTreeView.Loaded;
598     begin
599     inherited Loaded;
600     Reinitialise
601     end;
602    
603     procedure TIBTreeView.NodeChanged(Node: TTreeNode;
604     ChangeEvent: TTreeNodeChangeReason);
605     begin
606     inherited NodeChanged(Node, ChangeEvent);
607     if not FNoAddNodeToDataset and not FUpdating then
608     case ChangeEvent of
609     ncTextChanged:
610     NodeUpdated(Node);
611     ncParentChanged:
612     NodeMoved(Node);
613     end;
614     end;
615    
616     procedure TIBTreeView.Notification(AComponent: TComponent; Operation: TOperation
617     );
618     begin
619     inherited Notification(AComponent, Operation);
620     if (Operation = opRemove) and
621     (FDataLink <> nil) and (AComponent = DataSource) then DataSource := nil;
622     end;
623    
624     procedure TIBTreeView.Reinitialise;
625     begin
626     if [csDesigning,csLoading] * ComponentState <> [] then Exit;
627     FLastSelected := GetNodePath(Selected);
628     Items.Clear;
629     end;
630    
631     constructor TIBTreeView.Create(TheComponent: TComponent);
632     begin
633     inherited Create(TheComponent);
634     FDataLink := TIBTreeViewDatalink.Create(self);
635     end;
636    
637     destructor TIBTreeView.Destroy;
638     begin
639     if assigned(FDataLink) then FDataLink.Free;
640     inherited Destroy;
641     end;
642    
643     function TIBTreeView.FindNode(KeyValuePath: array of variant;
644     SelectNode: boolean): TIBTreeNode;
645     var Node: TTreeNode;
646     i,j: integer;
647     begin
648     Result := nil;
649     FLocatingNode := true;
650     try
651     for j := 0 to Items.TopLvlCount - 1 do
652     begin
653     Node := Items.TopLvlItems[j];
654     i := 0;
655     Node.Expand(false);
656     while assigned(Node) do
657     begin
658     if TIBTreeNode(Node).KeyValue = KeyValuePath[i] then
659     begin
660     Inc(i);
661     if i = Length(KeyValuePath) then
662     begin
663     Result := TIBTreeNode(Node);
664     if SelectNode then
665     Selected := Node;
666     Exit
667     end
668     else
669     begin
670     Node.Expand(false);
671     Node := Node.GetFirstChild;
672     end
673     end
674     else
675     Node := Node.GetNextSibling
676     end
677     end
678     finally
679     FLocatingNode := false
680     end
681     end;
682    
683     function TIBTreeView.FindNode(KeyValue: variant): TIBTreeNode;
684     var i: integer;
685     begin
686     Result := nil;
687     if (Selected <> nil) and (TIBTreeNode(Selected).KeyValue = KeyValue) then
688     Result := TIBTreeNode(Selected)
689     else
690     {Find it the hard way}
691     begin
692     FullExpand;
693     for i := 0 to Items.Count -1 do
694     if TIBTreeNode(Items[i]).KeyValue = KeyValue then
695     begin
696     Result := TIBTreeNode(Items[i])
697     end;
698     end;
699     end;
700    
701     function TIBTreeView.GetNodePath(Node: TTreeNode): TVariantArray;
702     var aParent: TTreeNode;
703     i: integer;
704     begin
705     if not assigned(Node) or not (Node is TIBTreeNode) then
706     SetLength(Result,0)
707     else
708     begin
709     {Count length of Path}
710     i := 1;
711     aParent := Node.Parent;
712     while (aParent <> nil) do
713     begin
714     Inc(i);
715     aParent := aParent.Parent
716     end;
717    
718     {Save Path}
719     Setlength(Result,i);
720     while i > 0 do
721     begin
722     Dec(i);
723     Result[i] := TIBTreeNode(Node).KeyValue;
724     Node := Node.Parent
725     end;
726     end;
727     end;
728    
729     { TIBTreeViewDatalink }
730    
731     procedure TIBTreeViewDatalink.ActiveChanged;
732     begin
733     FOwner.ActiveChanged(self)
734     end;
735    
736     procedure TIBTreeViewDatalink.DataEvent(Event: TDataEvent; Info: Ptrint);
737     begin
738     if (Event = deCheckBrowseMode) and (Info = 1) and not DataSet.Active then
739     begin
740     if (DataSet is TIBDataSet) then
741     FOwner.UpdateSQL(self,TIBDataSet(DataSet).Parser)
742     else
743     if (DataSet is TIBQuery) then
744     FOwner.UpdateSQL(self,TIBQuery(DataSet).Parser)
745     end
746     else
747     if (Event = deCheckBrowseMode) and (Info = 2) and not DataSet.Active then
748     begin
749     if (DataSet is TIBDataSet) then
750     FOwner.UpdateParams(self,TIBDataSet(DataSet).Parser)
751     else
752     if (DataSet is TIBQuery) then
753     FOwner.UpdateParams(self,TIBQuery(DataSet).Parser)
754     end
755     else
756     inherited DataEvent(Event, Info);
757     end;
758    
759     procedure TIBTreeViewDatalink.DataSetChanged;
760     begin
761     FOwner.DataSetChanged(self)
762     end;
763    
764     procedure TIBTreeViewDatalink.RecordChanged(Field: TField);
765     begin
766     FOwner.RecordChanged(self,Field);
767     end;
768    
769     procedure TIBTreeViewDatalink.UpdateData;
770     begin
771     FOwner.UpdateData(self)
772     end;
773    
774     constructor TIBTreeViewDatalink.Create(AOwner: TIBTreeView);
775     begin
776     inherited Create;
777     FOwner := AOwner
778     end;
779    
780     end.