* * *

Author Topic: [SOLVED] VirtualTreeview search a column  (Read 1771 times)

JD

  • Hero Member
  • *****
  • Posts: 1728
[SOLVED] VirtualTreeview search a column
« on: January 24, 2018, 04:32:50 pm »
Hi there everyone,

I'm trying to simulate the way a TTreeFilterEdit works when it incrementally searches a TTreeView USING just a VirtualTreeView and an Edit control.

How do I use the Edit control's OnChange event to achieve this?

I attach a sample project (slightly modified from GetMem's example)

Thanks,

JD
« Last Edit: January 24, 2018, 05:32:41 pm by JD »
Windows (10, 7) - Lazarus 1.8/FPC 3.0.4, NewPascal, Delphi
Linux Mint Cinnamon  - Lazarus 1.8/FPC 3.0.4, NewPascal

Indy 10.6 series; mORMot; Zeos 7.2.1; SQLite, Firebird, PostgreSQL & MariaDB; VirtualTreeView 5.5.3 R1

GetMem

  • Hero Member
  • *****
  • Posts: 3194
Re: VirtualTreeview search a column
« Reply #1 on: January 24, 2018, 04:58:23 pm »
Like this:
Code: Pascal  [Select]
  1. procedure TForm1.FilterTree(const AColumn: Integer; AText: String);
  2. var
  3.   Node: PVirtualNode;
  4. begin
  5.   Node := ATree.GetFirst;
  6.   while Assigned(Node) do
  7.   begin
  8.     if Pos(UpperCase(AText), UpperCase(ATree.Text[Node, AColumn])) > 0 then
  9.       ATree.IsVisible[Node] := True
  10.     else
  11.       ATree.IsVisible[Node] := False;
  12.     Node := ATree.GetNext(Node);
  13.   end;
  14. end;
  15.  
  16. procedure TForm1.ResetTree;
  17. var
  18.   Node: PVirtualNode;
  19. begin
  20.   Node := ATree.GetFirst;
  21.   while Assigned(Node) do
  22.   begin
  23.     ATree.IsVisible[Node] := True;
  24.     Node := ATree.GetNext(Node);
  25.   end;
  26. end;
  27.  
  28. procedure TForm1.Edit2Change(Sender: TObject);
  29. begin
  30.   if Length(Edit2.Text) > 0 then
  31.     FilterTree(ComboBox1.ItemIndex, Edit2.Text)
  32.   else
  33.     ResetTree;
  34. end;
  35.  
  36. procedure TForm1.ATreeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  37.   Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
  38. begin
  39.   CellText := IntTostr(Column) + IntToStr(Node^.Index);
  40. end;

I would also put a reset button,  OnButtonClick you can call ResetTree method.

JD

  • Hero Member
  • *****
  • Posts: 1728
Re: VirtualTreeview search a column
« Reply #2 on: January 24, 2018, 05:08:03 pm »
Great! Works perfectly. Thanks a lot GetMem!!
Windows (10, 7) - Lazarus 1.8/FPC 3.0.4, NewPascal, Delphi
Linux Mint Cinnamon  - Lazarus 1.8/FPC 3.0.4, NewPascal

Indy 10.6 series; mORMot; Zeos 7.2.1; SQLite, Firebird, PostgreSQL & MariaDB; VirtualTreeView 5.5.3 R1

JD

  • Hero Member
  • *****
  • Posts: 1728
Re: [SOLVED] VirtualTreeview search a column
« Reply #3 on: January 24, 2018, 05:24:41 pm »
In another variation, what if I just want it NOT to filter the VirtualTreeView BUT to go to and highlight the item searched for or the row where the item is located in the VirtualTreeView.

thanks

JD
« Last Edit: January 24, 2018, 05:33:01 pm by JD »
Windows (10, 7) - Lazarus 1.8/FPC 3.0.4, NewPascal, Delphi
Linux Mint Cinnamon  - Lazarus 1.8/FPC 3.0.4, NewPascal

Indy 10.6 series; mORMot; Zeos 7.2.1; SQLite, Firebird, PostgreSQL & MariaDB; VirtualTreeView 5.5.3 R1

JD

  • Hero Member
  • *****
  • Posts: 1728
Re: VirtualTreeview search a column
« Reply #4 on: January 24, 2018, 05:30:36 pm »
It's OK. I found it. I just replace ATree.IsVisible[Node] := True with ATree.Selected[Node] := True

Thanks a lot,

JD
Windows (10, 7) - Lazarus 1.8/FPC 3.0.4, NewPascal, Delphi
Linux Mint Cinnamon  - Lazarus 1.8/FPC 3.0.4, NewPascal

Indy 10.6 series; mORMot; Zeos 7.2.1; SQLite, Firebird, PostgreSQL & MariaDB; VirtualTreeView 5.5.3 R1

GetMem

  • Hero Member
  • *****
  • Posts: 3194
Re: [SOLVED] VirtualTreeview search a column
« Reply #5 on: January 24, 2018, 05:40:35 pm »
Quote
It's OK. I found it. I just replace ATree.IsVisible[Node] := True with ATree.Selected[Node] := True
What if the node is outside the visible area, you need to scroll the tree:
Code: Pascal  [Select]
  1. ATree.Selected[Node] := True;
  2. ATree.TopNode := Node;

What if there are multiple search results? Did you set toMultiSelect to true?

JD

  • Hero Member
  • *****
  • Posts: 1728
Re: [SOLVED] VirtualTreeview search a column
« Reply #6 on: January 24, 2018, 05:58:56 pm »
Thanks for the TopNode tip. I did that in a StringGrid using the TopRow property. I did not know TopNode had the same behaviour in VirtualTreeView.

I did not set toMultiSelect to True. What will be the behaviour if it is set to True? Will all the nodes with the search results be selected at once?

JD
Windows (10, 7) - Lazarus 1.8/FPC 3.0.4, NewPascal, Delphi
Linux Mint Cinnamon  - Lazarus 1.8/FPC 3.0.4, NewPascal

Indy 10.6 series; mORMot; Zeos 7.2.1; SQLite, Firebird, PostgreSQL & MariaDB; VirtualTreeView 5.5.3 R1

GetMem

  • Hero Member
  • *****
  • Posts: 3194
Re: [SOLVED] VirtualTreeview search a column
« Reply #7 on: January 24, 2018, 06:35:02 pm »
Quote
What will be the behaviour if it is set to True? Will all the nodes with the search results be selected at once?
Yes.  If you don't want to use multiselect, there is another solution:
Code: Pascal  [Select]
  1. type
  2.   PData = ^TData;
  3.   TData = record
  4.     FHighlight: Boolean;
  5.   end;
  6.  
  7. //...
  8. procedure TForm1.btnAddDataClick(Sender: TObject);
  9. var
  10.   //...
  11.   Data: PData;
  12. begin
  13.   //...
  14.   for intGridCol := 0 to 55 do
  15.   begin
  16.     Node := ATree.AddChild(nil);
  17.     Data := ATree.GetNodeData(Node);
  18.     Data^.FHighLight := False;
  19.   end;
  20.  ATree.Colors.UnfocusedSelectionColor := ATree.Colors.FocusedSelectionColor;
  21. end;              
  22.  
  23. procedure TForm1.FilterTree(const AColumn: Integer; AText: String);
  24. var
  25.   Node: PVirtualNode;
  26.   Data: PData;
  27. begin
  28.   Node := ATree.GetFirst;
  29.   while Assigned(Node) do
  30.   begin
  31.     Data := ATree.GetNodeData(Node);
  32.     if Pos(UpperCase(AText), UpperCase(ATree.Text[Node, AColumn])) > 0 then
  33.       Data^.FHighLight := True
  34.     else
  35.       Data^.FHighLight := False;
  36.     ATree.ReinitNode(Node, False);
  37.     ATree.RepaintNode(Node);
  38.     Node := ATree.GetNext(Node);
  39.   end;
  40. end;
  41.  
  42. procedure TForm1.ResetTree;
  43. var
  44.   Node: PVirtualNode;
  45.   Data: PData;
  46. begin
  47.   Node := ATree.GetFirst;
  48.   while Assigned(Node) do
  49.   begin
  50.     Data := ATree.GetNodeData(Node);
  51.     Data^.FHighLight := False;
  52.     ATree.ReinitNode(Node, False);
  53.     ATree.RepaintNode(Node);
  54.     Node := ATree.GetNext(Node);
  55.   end;
  56. end;
  57.  
  58. procedure TForm1.ATreeBeforeCellPaint(Sender: TBaseVirtualTree;
  59.   TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  60.   CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect);
  61. var
  62.   Data: PData;
  63. begin
  64.   if CellPaintMode = cpmPaint then
  65.   begin
  66.     Data := Sender.GetNodeData(Node);
  67.     if (Node <> Sender.FocusedNode) then
  68.     begin
  69.       if Data^.FHighLight then
  70.         TargetCanvas.Brush.Color := $00E6FFE6
  71.       else
  72.         TargetCanvas.Brush.Color := TBaseVirtualTree(Sender).GetDefaultColor(dctBrush);
  73.     end
  74.     else
  75.       TargetCanvas.Brush.Color := ATree.Colors.FocusedSelectionColor;
  76.     TargetCanvas.FillRect(CellRect);
  77.   end;
  78. end;                
  79.  


Of course it all depends on the requirements.


JD

  • Hero Member
  • *****
  • Posts: 1728
Re: [SOLVED] VirtualTreeview search a column
« Reply #8 on: January 24, 2018, 08:06:48 pm »
Cool! :D Thanks a million for the tips and code, GetMem. They made all the difference.

Cheers,

JD
Windows (10, 7) - Lazarus 1.8/FPC 3.0.4, NewPascal, Delphi
Linux Mint Cinnamon  - Lazarus 1.8/FPC 3.0.4, NewPascal

Indy 10.6 series; mORMot; Zeos 7.2.1; SQLite, Firebird, PostgreSQL & MariaDB; VirtualTreeView 5.5.3 R1

GetMem

  • Hero Member
  • *****
  • Posts: 3194
Re: [SOLVED] VirtualTreeview search a column
« Reply #9 on: January 24, 2018, 08:34:46 pm »
Quote
Cool! :D Thanks a million for the tips and code, GetMem. They made all the difference.
You're welcome! I attach the modified demo project,  maybe someone will need similar solution in the future.

JD

  • Hero Member
  • *****
  • Posts: 1728
Re: [SOLVED] VirtualTreeview search a column
« Reply #10 on: January 24, 2018, 08:59:19 pm »
Quote
Cool! :D Thanks a million for the tips and code, GetMem. They made all the difference.
You're welcome! I attach the modified demo project,  maybe someone will need similar solution in the future.

Once again. Thanks a million. I think with this I can even replace my StringGrid codes.  :D

JD
Windows (10, 7) - Lazarus 1.8/FPC 3.0.4, NewPascal, Delphi
Linux Mint Cinnamon  - Lazarus 1.8/FPC 3.0.4, NewPascal

Indy 10.6 series; mORMot; Zeos 7.2.1; SQLite, Firebird, PostgreSQL & MariaDB; VirtualTreeView 5.5.3 R1

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus