Lazarus

Programming => LCL => Topic started by: RuudB on December 09, 2017, 12:38:43 pm

Title: TreeView + Checkbox
Post by: RuudB on December 09, 2017, 12:38:43 pm
Hello,

I ran into a program, DirSync Pro, https://www.dirsyncpro.org/ (https://www.dirsyncpro.org/) that enables you to synchronize directories using so called jobs. These jobs are shown in a TreeView. In this case one can select which job to run or not by (de)selecting a checkbox in front of the text of the item, see attachment. I know Lazarus has this Treeview but couldn't find anything with an extra checkbox. OK, then something else has to be used.
But looking at the Project Inspector I noticed it uses a TreeView as well. And each items has a little icon in front of the text. As Lazarus can be compiled by Lazarus (AFAIK), I looked for this kind of TreeView but didn't find anything. If these icons are possible, what else is possible?

Thank you for any info!

Kind regards, Ruud Baltissen


Title: Re: TreeView + Checkbox
Post by: GetMem on December 09, 2017, 01:38:04 pm
Hi RuudB,

Welcome to the forum. TTreeView is limited in many ways,  I would go with TVirtualStringTree instead. It has check support among many things, is fast, works well in every major widget set.  You can download it from the following webpage: https://github.com/blikblum/VirtualTreeView-Lazarus/releases . You have to install lclextensions package first.

PS: If you have questions regarding VST don't hesitate to ask.

regards,
GetMem
Title: Re: TreeView + Checkbox
Post by: wp on December 09, 2017, 02:20:31 pm
Maybe TTreeView has builtin checkboxes somewhere, but I never was successful with this. Instead I usually add a second image list which is linked to StateImages of the treeview; this imagelist contains two icons, a checked and a non-checked icon. The "StateIndex" of the tree items is used to decide which one of the icons is selected. The state icons are displayed in addition to any other node icons.

These functions facilitate accessing the checked state:
Code: Pascal  [Select][+][-]
  1. const
  2.   ImgIndexChecked = 0;   // Image index of checked icon
  3.   ImgIndexUnchecked = 1;  // Image index of unchecked icon
  4.  
  5. procedure CheckNode(Node: TTreeNode; Checked:boolean);
  6. begin
  7.   if Assigned(Node) then
  8.     if Checked then
  9.       Node.StateIndex := ImgIndexChecked      
  10.     else
  11.       Node.StateIndex := ImgIndexUnchecked;  
  12. end;
  13.  
  14. procedure ToggleTreeViewCheckBoxes(Node: TTreeNode);
  15. begin
  16.   if Assigned(Node) then begin
  17.     if Node.StateIndex = ImgIndexUnchecked then
  18.       Node.StateIndex := ImgIndexChecked
  19.     else
  20.     if Node.StateIndex = ImgIndexChecked then
  21.       Node.StateIndex := ImgIndexUnchecked
  22.   end;
  23. end;
  24.  
  25. function NodeChecked(ANode:TTreeNode): Boolean;
  26. begin
  27.   result := (ANode.StateIndex = ImgIndexChecked);
  28. end;

Finally you must hook  into the Click event to catch the clicks onto the state icons:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.TreeView1Click(Sender: TObject);
  2. var
  3.   P: TPoint;
  4.   node: TTreeNode;
  5.   ht: THitTests;
  6. begin
  7.   GetCursorPos(P);
  8.   P := TreeView1.ScreenToClient(P);
  9.   ht := TreeView1.GetHitTestInfoAt(P.X, P.Y);
  10.   if (htOnStateIcon in ht) then begin
  11.     node := TreeView1.GetNodeAt(P.X, P.Y);
  12.     ToggleTreeViewCheckBoxes(node);
  13.     [...]
  14.  

Title: Re: TreeView + Checkbox
Post by: ASerge on December 09, 2017, 03:15:11 pm
This will fill the ImageList with checkboxes:
Code: Pascal  [Select][+][-]
  1. uses ImgList, LCLIntf, Themes;
  2.  
  3. procedure FillImageListWithChecks(ImageList: TCustomImageList);
  4.  
  5.   procedure DrawCheck(Canvas: TCanvas; Checked: Boolean; const Rect: TRect);
  6.   const
  7.     CCheckedButtons: array [Boolean] of TThemedButton =
  8.       (tbCheckBoxUncheckedNormal, tbCheckBoxCheckedNormal);
  9.   begin
  10.     Canvas.FillRect(Rect);
  11.     ThemeServices.DrawElement(Canvas.Handle, ThemeServices.GetElementDetails(
  12.       CCheckedButtons[Checked]), Rect);
  13.   end;
  14.  
  15. var
  16.   Checks: TBitmap;
  17.   W, H: Integer;
  18.   OneCheckRect: TRect;
  19.   Canvas: TCanvas;
  20. begin
  21.   if ImageList = nil then
  22.     Exit;
  23.   H := GetSystemMetrics(SM_CYMENUCHECK);
  24.   W := GetSystemMetrics(SM_CXMENUCHECK);
  25.   ImageList.Height := H;
  26.   ImageList.Width := W;
  27.   Checks := TBitmap.Create;
  28.   try
  29.     Checks.Height := H;
  30.     Checks.Width := 2 * W;
  31.     OneCheckRect := Rect(0, 0, W, H);
  32.     Canvas := Checks.Canvas;
  33.     DrawCheck(Canvas, False, OneCheckRect);
  34.     OffsetRect(OneCheckRect, W, 0);
  35.     DrawCheck(Canvas, True, OneCheckRect);
  36.     ImageList.AddMasked(Checks, Canvas.Brush.Color);
  37.   finally
  38.     Checks.Free;
  39.   end;
  40. end;
  41. ...
  42. FillImageListWithChecks(TreeView1.StateImages);
Title: Re: TreeView + Checkbox
Post by: RuudB on December 09, 2017, 04:46:39 pm
Hallo GetMem,
...  I would go with TVirtualStringTree instead. ...
I downloaded both plus the demo. Then I had to find out how to use packages and how to install them. But when compiling one of the example, it couldn't find the unit VirtualTrees. So I to pay attention to the reply of "wp". And here I got results. But read it an be surprised  :)

Anyway thank you for your reply. I will try later again to see what went wrong.

Kind regards/groetjes, Ruud Baltissen
www.baltissen.org
Title: Re: TreeView + Checkbox
Post by: RuudB on December 09, 2017, 04:58:17 pm
... Instead I usually add a second image list which is linked to StateImages of the treeview; this imagelist contains two icons, a checked and a non-checked icon. ...
I first tried your code but that didn't work at all. But the reason could be that hadn't loaded an ImageList yet (never heard of it). So I started looking, found it, looked for some more explanation on the Web how to use it, just double-click it, but then bumped in an article about the use of it in combination with TreeView. It was quite simple:

  TreeView1.StateImages :=ImageList1;
  TreeView1.Images :=ImageList1;
....
  NewNode := Treeview1.Items.Add (nil, 'All jobs');
  TreeView1.Items[0].Selected := True;
  NewNode.ImageIndex :=0;
  NewNode.SelectedIndex :=1;
  NewNode.StateIndex :=2;

This "All jobs" node had a V in front of it. (This V was an icon I had to make myself). But to be honest, I have not a complete idea what is going on but I will find out by playing with the numbers a bit....

Kind regards/groetjes, Ruud Baltissen
www.baltissen.org
Title: Re: TreeView + Checkbox
Post by: GetMem on December 09, 2017, 05:09:47 pm
@RuudB
Quote
I downloaded both plus the demo. Then I had to find out how to use packages and how to install them. But when compiling one of the example, it couldn't find the unit VirtualTrees.
Most likely you did not install the packages correctly. Extract the content of lclextensions-0.6.1.zip and virtualtreeview-5.5.3-R1.zip to two separate folder. Start Lazarus, go to Main menu-->Package-->Open Package File(.lpk). Locate lclextensions_package.lpk, press the "Compile" toolbutton then the "Use-->Install" button, choose to rebuild IDE. Do the same for package virtualtreeview_package.lpk. Now you can open/compile/run the "Advanced" project from the examples directory.

Title: Re: TreeView + Checkbox
Post by: RuudB on December 09, 2017, 06:47:16 pm
.... Now you can open/compile/run the "Advanced" project from the examples directory.
I did exactly as described. In the last line of the Package menu you can check what has been installed and both packages show as "installed". But yet the unit VirtualTrees is not found.

Kind regards/groetjes, Ruud Baltissen
www.baltissen.org
Title: Re: TreeView + Checkbox
Post by: GetMem on December 09, 2017, 06:52:44 pm
Quote
I did exactly as described. In the last line of the Package menu you can check what has been installed and both packages show as "installed". But yet the unit VirtualTrees is not found.
Page "Virtual Controls" is visible in the Component Palette?
Title: Re: TreeView + Checkbox
Post by: RuudB on December 09, 2017, 07:34:12 pm
Page "Virtual Controls" is visible in the Component Palette?
No, see attached PNG.
Title: Re: TreeView + Checkbox
Post by: GetMem on December 09, 2017, 07:42:43 pm
@ RuudB
Please update to Lazarus 1.8. Your version is way to old.
Title: Re: TreeView + Checkbox
Post by: JuhaManninen on December 09, 2017, 08:17:44 pm
@ RuudB
Please update to Lazarus 1.8. Your version is way to old.
Huh, indeed! Lazarus 1.2.6 was released well over 3 years ago. You forgot to mention it. People assume you have the latest version unless told otherwise.
May I ask why you have such an old version?

Title: Re: TreeView + Checkbox
Post by: wp on December 09, 2017, 09:45:54 pm
Since you seem to have problems applying my code snippets above I am attaching a complete demo project showing the TTreeView with checkbox stateimages and additional node images. It compiles with even Laz 1.0 (although the two images per node are displayed differently than today).
Title: Re: TreeView + Checkbox
Post by: RuudB on December 10, 2017, 09:58:18 am
May I ask why you have such an old version?
For the very simple reason that I don't use Lazarus that often and it works very fine for the few programs I wrote for my self and therefore I never ever thought about checking for an update :)
Title: Re: TreeView + Checkbox
Post by: RuudB on December 10, 2017, 10:02:16 am
@ RuudB
Please update to Lazarus 1.8. Your version is way to old.
I tried yesterday evening and this morning. But for one or another reason 1.8.0 isn't able to compile and ends with an error that it cannot find the unit Interfaces. See more details here: http://forum.lazarus.freepascal.org/index.php/topic,39242.0.html (http://forum.lazarus.freepascal.org/index.php/topic,39242.0.html)
So for the moment it remains 1.2.6  :)

Kind regards/groetjes, Ruud Baltissen
Title: Re: TreeView + Checkbox
Post by: RuudB on December 10, 2017, 10:13:03 am
... I am attaching a complete demo project ...
That explained things very well, thank you very much!

Kind regards/groetjs, Ruud Baltissen
Title: Re: TreeView + Checkbox
Post by: GetMem on December 10, 2017, 10:47:56 am
@RuudB

A lot of development has been done since 1.2.6. This is the only reason I suggested to install 1.8. However if you fine with 1.2, by all mean stay with it, 1.2 was a great release too.  You can use @wp's nice example to support checkboxes in TTreeView.
Title: Re: TreeView + Checkbox
Post by: geraldholdsworth on June 10, 2021, 05:09:56 pm
I am attaching a complete demo project showing the TTreeView with checkbox stateimages and additional node images.

Excellent work, as always Werner.

However, I've taken this and added to it. You can now have intermediate nodes, if any of the child nodes do not match that of the parent. In addition, changing the option on a parent will drill down changing the option for the children and grandchildren (and so on). I've also added a line to deselect the node when clicked on. I'll work on how to just deselect this node while keeping the others selected (if they were).

And I've changed the graphics too - only because I didn't have the graphic for an intermediate (and its the graphics I'll be using in my project).
TinyPortal © 2005-2018