Recent

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

JD

  • Hero Member
  • *****
  • Posts: 1848
[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 - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe),
Linux Mint - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe)

mORMot; Zeos 8; SQLite, PostgreSQL & MariaDB; VirtualTreeView

balazsszekely

  • Guest
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: 1848
Re: VirtualTreeview search a column
« Reply #2 on: January 24, 2018, 05:08:03 pm »
Great! Works perfectly. Thanks a lot GetMem!!
Windows - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe),
Linux Mint - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe)

mORMot; Zeos 8; SQLite, PostgreSQL & MariaDB; VirtualTreeView

JD

  • Hero Member
  • *****
  • Posts: 1848
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 - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe),
Linux Mint - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe)

mORMot; Zeos 8; SQLite, PostgreSQL & MariaDB; VirtualTreeView

JD

  • Hero Member
  • *****
  • Posts: 1848
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 - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe),
Linux Mint - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe)

mORMot; Zeos 8; SQLite, PostgreSQL & MariaDB; VirtualTreeView

balazsszekely

  • Guest
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: 1848
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 - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe),
Linux Mint - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe)

mORMot; Zeos 8; SQLite, PostgreSQL & MariaDB; VirtualTreeView

balazsszekely

  • Guest
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: 1848
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 - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe),
Linux Mint - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe)

mORMot; Zeos 8; SQLite, PostgreSQL & MariaDB; VirtualTreeView

balazsszekely

  • Guest
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: 1848
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 - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe),
Linux Mint - Lazarus 2.1/FPC 3.2 (built using fpcupdeluxe)

mORMot; Zeos 8; SQLite, PostgreSQL & MariaDB; VirtualTreeView

 

TinyPortal © 2005-2018