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 217 by tony, Fri Mar 16 10:27:26 2018 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 >          if ImageIndexField <> '' then
371 >            Node.ImageIndex := DataSet.FieldByName(ImageIndexField).AsInteger;
372 >          if SelectedIndexField <> '' then
373 >            Node.SelectedIndex := DataSet.FieldByName(SelectedIndexField).AsInteger;
374 >          TIBTreeNode(Node).FKeyValue := DataSet.FieldByName(KeyField).AsVariant;
375 >          Node.HasChildren := (HasChildField = '') or (DataSet.FieldByName(HasChildField).AsInteger <> 0);
376 >          Inc(ChildCount);
377 >        end;
378          DataSet.Next
379        end;
380      finally
# Line 338 | Line 388 | end;
388  
389   procedure TIBTreeView.DataSetChanged(Sender: TObject);
390   begin
391 < //  Reinitialise
391 > //  Do nothing;
392   end;
393  
394   function TIBTreeView.GetDataSet: TDataSet;
# Line 391 | Line 441 | procedure TIBTreeView.RecordChanged(Send
441   var Node: TIBTreeNode;
442      Destination: TIBTreeNode;
443   begin
444 +  if DataSet.State = dsInsert then Exit;
445 +
446    if assigned(Field) and (Field.FieldName = TextField) then
447    begin
448      Node := FindNode(DataSet.FieldByName(KeyField).AsVariant);
# Line 405 | Line 457 | begin
457      end;
458    end
459    else
460 +  if assigned(Field) and (Field.FieldName = ImageIndexField) then
461 +  begin
462 +    Node := FindNode(DataSet.FieldByName(KeyField).AsVariant);
463 +    if assigned(Node) then
464 +    begin
465 +      FUpdating := true;
466 +      try
467 +        Node.ImageIndex := Field.AsInteger
468 +      finally
469 +        FUpdating := false
470 +      end;
471 +    end;
472 +  end
473 +  else
474    if assigned(Field) and (Field.FieldName = ParentField) then
475    begin
476      Node := FindNode(DataSet.FieldByName(KeyField).AsVariant);
# Line 415 | Line 481 | begin
481        else
482          Destination := FindNode(DataSet.FieldByName(ParentField).AsVariant);
483  
484 <      if Destination = Node.Parent then Exit;
484 >      if (Destination = nil) or (Destination = Node.Parent) then Exit;
485  
486        FUpdating := true;
487        try
# Line 434 | Line 500 | begin
500    Reinitialise
501   end;
502  
503 + procedure TIBTreeView.SetImageIndexField(AValue: string);
504 + begin
505 +  if FImageIndexField = AValue then Exit;
506 +  FImageIndexField := AValue;
507 +  Reinitialise
508 + end;
509 +
510   procedure TIBTreeView.SetKeyField(AValue: string);
511   begin
512    if FKeyField = AValue then Exit;
# Line 441 | Line 514 | begin
514    Reinitialise
515   end;
516  
517 + procedure TIBTreeView.SetSelectedIndexField(AValue: string);
518 + begin
519 +  if FSelectedIndexField = AValue then Exit;
520 +  FSelectedIndexField := AValue;
521 +  Reinitialise;
522 + end;
523 +
524   procedure TIBTreeView.SetTextField(AValue: string);
525   begin
526    if FTextField = AValue then Exit;
# Line 450 | Line 530 | end;
530  
531   procedure TIBTreeView.SetDataSource(AValue: TDataSource);
532   begin
533 <  FDataLink.DataSource := AValue
533 >  FDataLink.DataSource := AValue;
534 >  IBControlLinkChanged;
535   end;
536  
537   procedure TIBTreeView.SetParentField(AValue: string);
# Line 466 | Line 547 | begin
547    if Result then
548    begin
549      if DataSet.Active and (DataSet.RecordCount > 0)
550 <         and (Node.KeyValue = DataSet.FieldByName(KeyField).AsVariant) then Exit;
550 >         and DataSet.Locate(KeyField,Node.KeyValue,[]) then Exit;
551  
552      FUpdateNode := Node;
553      try
# Line 496 | Line 577 | procedure TIBTreeView.UpdateParams(Sende
577   begin
578    if not assigned(FExpandNode) and assigned(FUpdateNode)  then {Scrolling dataset}
579     begin
580 <     if (Sender as TDataLink).DataSet is TIBQuery then
581 <       TIBQuery((Sender as TDataLink).DataSet).ParamByName('IBX_KEY_VALUE').Value :=
580 >     if DataSource.DataSet is TIBQuery then
581 >       TIBQuery(DataSource.DataSet).ParamByName('IBX_KEY_VALUE').Value :=
582           FUpdateNode.KeyValue
583       else
584 <     if (Sender as TDataLink).DataSet is TIBDataSet then
585 <       TIBDataSet((Sender as TDataLink).DataSet).ParamByName('IBX_KEY_VALUE').Value :=
584 >     if DataSource.DataSet is TIBDataSet then
585 >       TIBDataSet(DataSource.DataSet).ParamByName('IBX_KEY_VALUE').Value :=
586           FUpdateNode.KeyValue
587     end
588    else
589    if assigned(FExpandNode) then
590    begin
591 <    if (Sender as TDataLink).DataSet is TIBQuery then
592 <      TIBQuery((Sender as TDataLink).DataSet).ParamByName('IBX_PARENT_VALUE').Value :=
591 >    if DataSource.DataSet is TIBQuery then
592 >      TIBQuery(DataSource.DataSet).ParamByName('IBX_PARENT_VALUE').Value :=
593          TIBTreeNode(FExpandNode).KeyValue
594      else
595 <    if (Sender as TDataLink).DataSet is TIBDataSet then
596 <      TIBDataSet((Sender as TDataLink).DataSet).ParamByName('IBX_PARENT_VALUE').Value :=
595 >    if DataSource.DataSet is TIBDataSet then
596 >      TIBDataSet(DataSource.DataSet).ParamByName('IBX_PARENT_VALUE').Value :=
597          TIBTreeNode(FExpandNode).KeyValue
598    end;
599   end;
# Line 527 | Line 608 | begin
608        Parser.Add2WhereClause(GetRelationNameQualifier + '"' + FParentField + '" is null')
609      else
610      if assigned(FExpandNode) then
611 +    begin
612        Parser.Add2WhereClause(GetRelationNameQualifier + '"' + FParentField + '" = :IBX_PARENT_VALUE');
613 +      Parser.Add2WhereClause(GetRelationNameQualifier + '"' + FKeyField + '" = :IBX_PARENT_VALUE',true);
614 +    end;
615   end;
616  
617   procedure TIBTreeView.Added(Node: TTreeNode);
# Line 589 | Line 673 | begin
673      FExpandNode := Node;
674      DataSet.Active := false;
675      DataSet.Active := true;
676 <    if assigned(Selected) then
593 <      ScrollToNode(TIBTreeNode(Selected))
676 >    Selected := Node;
677    end;
678   end;
679  
680 + procedure TIBTreeView.IBControlLinkChanged;
681 + begin
682 +  if assigned(DataSource) and (DataSource.DataSet <> nil) and (DataSource.DataSet is TIBParserDataset) then
683 +    FIBTreeViewControllink.IBDataSet := TIBCustomDataSet(DataSource.DataSet)
684 +  else
685 +    FIBTreeViewControllink.IBDataSet := nil;
686 + end;
687 +
688   procedure TIBTreeView.Loaded;
689   begin
690    inherited Loaded;
691 +  IBControlLinkChanged;
692    Reinitialise
693   end;
694  
# Line 618 | Line 710 | procedure TIBTreeView.Notification(AComp
710   begin
711    inherited Notification(AComponent, Operation);
712    if (Operation = opRemove) and
713 <     (FDataLink <> nil) and (AComponent = DataSource) then DataSource := nil;
713 >     (FDataLink <> nil) and (AComponent = DataSource) then
714 >     DataSource := nil;
715   end;
716  
717   procedure TIBTreeView.Reinitialise;
# Line 632 | Line 725 | constructor TIBTreeView.Create(TheCompon
725   begin
726    inherited Create(TheComponent);
727    FDataLink := TIBTreeViewDatalink.Create(self);
728 +  FIBTreeViewControlLink := TIBTreeViewControlLink.Create(self);
729   end;
730  
731   destructor TIBTreeView.Destroy;
732   begin
733    if assigned(FDataLink) then FDataLink.Free;
734 +  if assigned(FIBTreeViewControlLink) then FIBTreeViewControlLink.Free;
735    inherited Destroy;
736   end;
737  
738 < function TIBTreeView.FindNode(KeyValuePath: array of variant;
739 <  SelectNode: boolean): TIBTreeNode;
738 > function TIBTreeView.FindNode(KeyValuePath: TVariantArray; SelectNode: boolean
739 >  ): TIBTreeNode;
740   var Node: TTreeNode;
741      i,j: integer;
742   begin
743    Result := nil;
744 +  if Length(KeyValuePath) = 0 then Exit;
745 +
746    FLocatingNode := true;
747    try
748     for j := 0 to Items.TopLvlCount - 1 do
# Line 655 | Line 752 | begin
752      Node.Expand(false);
753      while assigned(Node)  do
754      begin
755 <      if TIBTreeNode(Node).KeyValue = KeyValuePath[i] then
755 >      if not VarIsNull(TIBTreeNode(Node).KeyValue) and
756 >                        (TIBTreeNode(Node).KeyValue = KeyValuePath[i]) then
757        begin
758          Inc(i);
759          if i = Length(KeyValuePath) then
# Line 733 | Line 831 | begin
831    FOwner.ActiveChanged(self)
832   end;
833  
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
834   procedure TIBTreeViewDatalink.DataSetChanged;
835   begin
836    FOwner.DataSetChanged(self)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines