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 21 by tony, Thu Feb 26 10:33:34 2015 UTC vs.
Revision 272 by tony, Mon Feb 4 13:34:37 2019 UTC

# Line 15 | Line 15
15   *
16   *  The Initial Developer of the Original Code is Tony Whyman.
17   *
18 < *  The Original Code is (C) 2011 Tony Whyman, MWA Software
18 > *  The Original Code is (C) 2015 Tony Whyman, MWA Software
19   *  (http://www.mwasoftware.co.uk).
20   *
21   *  All Rights Reserved.
# Line 31 | Line 31 | interface
31  
32   uses
33    Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ComCtrls,
34 <  DB, IBSQLParser;
34 >  DB, IBSQLParser, IBCustomDataSet;
35  
36   type
37    {
# Line 52 | Line 52 | type
52      FOwner: TIBTreeView;
53    protected
54      procedure ActiveChanged; override;
55    procedure DataEvent(Event: TDataEvent; Info: Ptrint); override;
55      procedure DataSetChanged; override;
56      procedure RecordChanged(Field: TField); override;
57      procedure UpdateData; override;
# Line 60 | Line 59 | type
59      constructor Create(AOwner: TIBTreeView);
60    end;
61  
62 +  { TIBTreeViewControlLink }
63 +
64 +  TIBTreeViewControlLink = class(TIBControlLink)
65 +  private
66 +    FOwner: TIBTreeView;
67 +  protected
68 +    procedure UpdateSQL(Sender: TObject); override;
69 +    procedure UpdateParams(Sender: TObject); override;
70 +  public
71 +    constructor Create(AOwner: TIBTreeView);
72 +  end;
73 +
74    { 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;
# Line 74 | Line 86 | type
86    private
87      { Private declarations }
88      FDataLink: TIBTreeViewDatalink;
89 +    FIBTreeViewControlLink: TIBTreeViewControlLink;
90      FHasChildField: string;
91 +    FImageIndexField: string;
92      FKeyField: string;
93 +    FSelectedIndexField: string;
94      FTextField: string;
95      FParentField: string;
96      FExpandNode: TTreeNode;
# Line 93 | Line 108 | type
108      function GetDataSource: TDataSource;
109      function GetRelationNameQualifier: string;
110      function GetSelectedKeyValue: variant;
111 +    procedure IBControlLinkChanged;
112      procedure NodeMoved(Node: TTreeNode);
113      procedure NodeUpdated(Node: TTreeNode);
114      procedure RecordChanged(Sender: TObject; Field: TField);
115      procedure SetHasChildField(AValue: string);
116 +    procedure SetImageIndexField(AValue: string);
117      procedure SetKeyField(AValue: string);
118 +    procedure SetSelectedIndexField(AValue: string);
119      procedure SetTextField(AValue: string);
120      procedure SetDataSource(AValue: TDataSource);
121      procedure SetParentField(AValue: string);
# Line 121 | Line 139 | type
139      { Public declarations }
140      constructor Create(TheComponent: TComponent); override;
141      destructor Destroy; override;
142 <    function FindNode(KeyValuePath: array of variant; SelectNode: boolean): TIBTreeNode; overload;
142 >    function FindNode(KeyValuePath: TVariantArray; SelectNode: boolean): TIBTreeNode; overload;
143      function FindNode(KeyValue: variant): TIBTreeNode; overload;
144      function GetNodePath(Node: TTreeNode): TVariantArray;
145      property DataSet: TDataSet read GetDataSet;
# Line 153 | Line 171 | type
171      property Images;
172      property Indent;
173      property HasChildField: string read FHasChildField write SetHasChildField;
174 +    property ImageIndexField: string read FImageIndexField write SetImageIndexField;
175 +    property SelectedIndexField: string read FSelectedIndexField write SetSelectedIndexField;
176      property KeyField: string read FKeyField write SetKeyField;
177      property MultiSelect;
178      property MultiSelectStyle;
# Line 232 | Line 252 | type
252  
253   implementation
254  
255 < uses IBQuery,IBCustomDataSet, Variants;
255 > uses IBQuery,Variants;
256  
257   function StrIntListToVar(s: string): TVariantArray;
258   var i, idx: integer;
# Line 268 | Line 288 | begin
288          raise Exception.Create('Ordinal Type Expected when converting to integer string');
289   end;
290  
291 + { TIBTreeViewControlLink }
292 +
293 + constructor TIBTreeViewControlLink.Create(AOwner: TIBTreeView);
294 + begin
295 +  inherited Create;
296 +  FOwner := AOwner;
297 + end;
298 +
299 + procedure TIBTreeViewControlLink.UpdateParams(Sender: TObject);
300 + begin
301 +  FOwner.UpdateParams(self,TIBParserDataSet(Sender).Parser)
302 + end;
303 +
304 + procedure TIBTreeViewControlLink.UpdateSQL(Sender: TObject);
305 + begin
306 +  FOwner.UpdateSQL(self,TIBParserDataSet(Sender).Parser)
307 + end;
308 +
309   { TIBTreeNode }
310  
311 + constructor TIBTreeNode.Create(AnOwner: TTreeNodes);
312 + begin
313 +  inherited Create(AnOwner);
314 +  FKeyValue := NULL;
315 + end;
316 +
317   procedure TIBTreeNode.DeleteAll;
318   var Node, NextNode: TTreeNode;
319   begin
# Line 287 | Line 331 | end;
331   { TIBTreeView }
332  
333   procedure TIBTreeView.ActiveChanged(Sender: TObject);
290 var AtTopLevel: boolean;
334   begin
335    if (csDesigning in ComponentState) then Exit;
336 +  IBControlLinkChanged;
337    if assigned(DataSet) and not DataSet.Active then
338    begin
339      if not assigned(FExpandNode) and not assigned(FUpdateNode) then {must really be closing}
# Line 297 | Line 341 | begin
341    end
342    else
343    begin
300    AtTopLevel := Items.TopLvlCount = 0;
344      AddNodes;
345      if not FLocatingNode and (Selected = nil) and (Items.TopLvlCount > 0) then
346      begin
# Line 321 | Line 364 | begin
364        DataSet.First;
365        while not DataSet.EOF do
366        begin
367 <        Node := Items.AddChild(FExpandNode,DataSet.FieldByName(TextField).AsString);
368 <        TIBTreeNode(Node).FKeyValue := DataSet.FieldByName(KeyField).AsVariant;
369 <        Node.HasChildren := (HasChildField = '') or (DataSet.FieldByName(HasChildField).AsInteger <> 0);
370 <        Inc(ChildCount);
367 >        if (FExpandNode = nil) or (TIBTreeNode(FExpandNode).KeyValue <> DataSet.FieldByName(KeyField).AsVariant) then
368 >        begin
369 >          Node := Items.AddChild(FExpandNode,DataSet.FieldByName(TextField).AsString);
370 >          Node.HasChildren := (HasChildField = '') or (DataSet.FieldByName(HasChildField).AsInteger <> 0);
371 >          Inc(ChildCount);
372 >        end;
373          DataSet.Next
374        end;
375      finally
# Line 338 | Line 383 | end;
383  
384   procedure TIBTreeView.DataSetChanged(Sender: TObject);
385   begin
386 < //  Reinitialise
386 > //  Do nothing;
387   end;
388  
389   function TIBTreeView.GetDataSet: TDataSet;
# Line 391 | Line 436 | procedure TIBTreeView.RecordChanged(Send
436   var Node: TIBTreeNode;
437      Destination: TIBTreeNode;
438   begin
439 +  if DataSet.State = dsInsert then Exit;
440 +
441    if assigned(Field) and (Field.FieldName = TextField) then
442    begin
443      Node := FindNode(DataSet.FieldByName(KeyField).AsVariant);
# Line 405 | Line 452 | begin
452      end;
453    end
454    else
455 +  if assigned(Field) and (Field.FieldName = ImageIndexField) then
456 +  begin
457 +    Node := FindNode(DataSet.FieldByName(KeyField).AsVariant);
458 +    if assigned(Node) then
459 +    begin
460 +      FUpdating := true;
461 +      try
462 +        Node.ImageIndex := Field.AsInteger
463 +      finally
464 +        FUpdating := false
465 +      end;
466 +    end;
467 +  end
468 +  else
469    if assigned(Field) and (Field.FieldName = ParentField) then
470    begin
471      Node := FindNode(DataSet.FieldByName(KeyField).AsVariant);
# Line 415 | Line 476 | begin
476        else
477          Destination := FindNode(DataSet.FieldByName(ParentField).AsVariant);
478  
479 <      if Destination = Node.Parent then Exit;
479 >      if (Destination = nil) or (Destination = Node.Parent) then Exit;
480  
481        FUpdating := true;
482        try
# Line 434 | Line 495 | begin
495    Reinitialise
496   end;
497  
498 + procedure TIBTreeView.SetImageIndexField(AValue: string);
499 + begin
500 +  if FImageIndexField = AValue then Exit;
501 +  FImageIndexField := AValue;
502 +  Reinitialise
503 + end;
504 +
505   procedure TIBTreeView.SetKeyField(AValue: string);
506   begin
507    if FKeyField = AValue then Exit;
# Line 441 | Line 509 | begin
509    Reinitialise
510   end;
511  
512 + procedure TIBTreeView.SetSelectedIndexField(AValue: string);
513 + begin
514 +  if FSelectedIndexField = AValue then Exit;
515 +  FSelectedIndexField := AValue;
516 +  Reinitialise;
517 + end;
518 +
519   procedure TIBTreeView.SetTextField(AValue: string);
520   begin
521    if FTextField = AValue then Exit;
# Line 450 | Line 525 | end;
525  
526   procedure TIBTreeView.SetDataSource(AValue: TDataSource);
527   begin
528 <  FDataLink.DataSource := AValue
528 >  FDataLink.DataSource := AValue;
529 >  IBControlLinkChanged;
530   end;
531  
532   procedure TIBTreeView.SetParentField(AValue: string);
# Line 466 | Line 542 | begin
542    if Result then
543    begin
544      if DataSet.Active and (DataSet.RecordCount > 0)
545 <         and (Node.KeyValue = DataSet.FieldByName(KeyField).AsVariant) then Exit;
545 >         and DataSet.Locate(KeyField,Node.KeyValue,[]) then Exit;
546  
547      FUpdateNode := Node;
548      try
# Line 496 | Line 572 | procedure TIBTreeView.UpdateParams(Sende
572   begin
573    if not assigned(FExpandNode) and assigned(FUpdateNode)  then {Scrolling dataset}
574     begin
575 <     if (Sender as TDataLink).DataSet is TIBQuery then
576 <       TIBQuery((Sender as TDataLink).DataSet).ParamByName('IBX_KEY_VALUE').Value :=
575 >     if DataSource.DataSet is TIBQuery then
576 >       TIBQuery(DataSource.DataSet).ParamByName('IBX_KEY_VALUE').Value :=
577           FUpdateNode.KeyValue
578       else
579 <     if (Sender as TDataLink).DataSet is TIBDataSet then
580 <       TIBDataSet((Sender as TDataLink).DataSet).ParamByName('IBX_KEY_VALUE').Value :=
579 >     if DataSource.DataSet is TIBDataSet then
580 >       TIBDataSet(DataSource.DataSet).ParamByName('IBX_KEY_VALUE').Value :=
581           FUpdateNode.KeyValue
582     end
583    else
584    if assigned(FExpandNode) then
585    begin
586 <    if (Sender as TDataLink).DataSet is TIBQuery then
587 <      TIBQuery((Sender as TDataLink).DataSet).ParamByName('IBX_PARENT_VALUE').Value :=
586 >    if DataSource.DataSet is TIBQuery then
587 >      TIBQuery(DataSource.DataSet).ParamByName('IBX_PARENT_VALUE').Value :=
588          TIBTreeNode(FExpandNode).KeyValue
589      else
590 <    if (Sender as TDataLink).DataSet is TIBDataSet then
591 <      TIBDataSet((Sender as TDataLink).DataSet).ParamByName('IBX_PARENT_VALUE').Value :=
590 >    if DataSource.DataSet is TIBDataSet then
591 >      TIBDataSet(DataSource.DataSet).ParamByName('IBX_PARENT_VALUE').Value :=
592          TIBTreeNode(FExpandNode).KeyValue
593    end;
594   end;
# Line 527 | Line 603 | begin
603        Parser.Add2WhereClause(GetRelationNameQualifier + '"' + FParentField + '" is null')
604      else
605      if assigned(FExpandNode) then
606 +    begin
607        Parser.Add2WhereClause(GetRelationNameQualifier + '"' + FParentField + '" = :IBX_PARENT_VALUE');
608 +      Parser.Add2WhereClause(GetRelationNameQualifier + '"' + FKeyField + '" = :IBX_PARENT_VALUE',true);
609 +    end;
610   end;
611  
612   procedure TIBTreeView.Added(Node: TTreeNode);
613   begin
614 <  if assigned(DataSet) and DataSet.Active and not FNoAddNodeToDataset then
614 >  if assigned(DataSet) and DataSet.Active then
615    begin
616 <    DataSet.Append;
616 >    if not FNoAddNodeToDataset then
617 >    begin
618 >      DataSet.Append;
619 >      if (Node.Text = '') and not DataSet.FieldByName(TextField).IsNull then
620 >         Node.Text := DataSet.FieldByName(TextField).AsString;
621 >      FModifiedNode := TIBTreeNode(Node);
622 >      FDataLink.UpdateRecord;
623 >    end;
624      TIBTreeNode(Node).FKeyValue := DataSet.FieldByName(KeyField).AsVariant;
625 <    if (Node.Text = '') and not DataSet.FieldByName(TextField).IsNull then
626 <       Node.Text := DataSet.FieldByName(TextField).AsString;
627 <    FModifiedNode := TIBTreeNode(Node);
628 <    FDataLink.UpdateRecord
625 >    if ImageIndexField <> '' then
626 >      Node.ImageIndex := DataSet.FieldByName(ImageIndexField).AsInteger;
627 >    if SelectedIndexField <> '' then
628 >      Node.SelectedIndex := DataSet.FieldByName(SelectedIndexField).AsInteger;
629    end;
630    inherited Added(Node);
631   end;
# Line 589 | Line 675 | begin
675      FExpandNode := Node;
676      DataSet.Active := false;
677      DataSet.Active := true;
678 <    if assigned(Selected) then
593 <      ScrollToNode(TIBTreeNode(Selected))
678 >    Selected := Node;
679    end;
680   end;
681  
682 + procedure TIBTreeView.IBControlLinkChanged;
683 + begin
684 +  if assigned(DataSource) and (DataSource.DataSet <> nil) and (DataSource.DataSet is TIBParserDataset) then
685 +    FIBTreeViewControllink.IBDataSet := TIBCustomDataSet(DataSource.DataSet)
686 +  else
687 +    FIBTreeViewControllink.IBDataSet := nil;
688 + end;
689 +
690   procedure TIBTreeView.Loaded;
691   begin
692    inherited Loaded;
693 +  IBControlLinkChanged;
694    Reinitialise
695   end;
696  
# Line 618 | Line 712 | procedure TIBTreeView.Notification(AComp
712   begin
713    inherited Notification(AComponent, Operation);
714    if (Operation = opRemove) and
715 <     (FDataLink <> nil) and (AComponent = DataSource) then DataSource := nil;
715 >     (FDataLink <> nil) and (AComponent = DataSource) then
716 >     DataSource := nil;
717   end;
718  
719   procedure TIBTreeView.Reinitialise;
# Line 632 | Line 727 | constructor TIBTreeView.Create(TheCompon
727   begin
728    inherited Create(TheComponent);
729    FDataLink := TIBTreeViewDatalink.Create(self);
730 +  FIBTreeViewControlLink := TIBTreeViewControlLink.Create(self);
731   end;
732  
733   destructor TIBTreeView.Destroy;
734   begin
735    if assigned(FDataLink) then FDataLink.Free;
736 +  if assigned(FIBTreeViewControlLink) then FIBTreeViewControlLink.Free;
737    inherited Destroy;
738   end;
739  
740 < function TIBTreeView.FindNode(KeyValuePath: array of variant;
741 <  SelectNode: boolean): TIBTreeNode;
740 > function TIBTreeView.FindNode(KeyValuePath: TVariantArray; SelectNode: boolean
741 >  ): TIBTreeNode;
742   var Node: TTreeNode;
743      i,j: integer;
744   begin
745    Result := nil;
746 +  if Length(KeyValuePath) = 0 then Exit;
747 +
748    FLocatingNode := true;
749    try
750     for j := 0 to Items.TopLvlCount - 1 do
# Line 655 | Line 754 | begin
754      Node.Expand(false);
755      while assigned(Node)  do
756      begin
757 <      if TIBTreeNode(Node).KeyValue = KeyValuePath[i] then
757 >      if not VarIsNull(TIBTreeNode(Node).KeyValue) and
758 >                        (TIBTreeNode(Node).KeyValue = KeyValuePath[i]) then
759        begin
760          Inc(i);
761          if i = Length(KeyValuePath) then
# Line 733 | Line 833 | begin
833    FOwner.ActiveChanged(self)
834   end;
835  
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
836   procedure TIBTreeViewDatalink.DataSetChanged;
837   begin
838    FOwner.DataSetChanged(self)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines