Tree Sorting


There are two ways to sort a tree. The first is extremely easy, just use the TTreeView.AlphaSort method. The tree will, obviously enough, be sorted alphabetically.

This type of simple sorting is more suitable for "simple" trees, like example 1 - 4. It is not good enough for more complex trees though.

Here is an example of an Alpha sorted tree


The problem here is that folder and file nodes are not grouped together. Optimally the same tree, once sorted, should look like this


In this tree files are always displayed before folders. The more complex the tree the more useful "grouping" becomes. TreeView's support user defined sorting, the method to call is TTreeView.CustomSort.

The CustomSort function takes 2 parameters
SortProc : TTVCompare SortProc is a callback function. This function is called by the TTreeView and compares pairs of nodes.
Data : LongInt You can pass any value to the callback function using this parameter. If you want to pass a pointer then just type cast it to an integer.
eg CustomSort( ..., integer(@Somthing) );

The callback function that is passed as param 1 is defined as follows

function(  Node1,  Node2 : TTreeNode;  Data : integer  ) : integer; stdcall;


What you have to do is compare Node1 and Node2, then return

Positive integer Node2 displayed before Node1
0 Nodes are equivalent
Negative integer Node1 displayed before Node2


The example callback function


   /////////////////////////////////////
   // Custom sort callback function
   /////////////////////////////////////
   function MyCustomSortProc(  Node1,  Node2 : TTreeNode;  Data : integer  ) : integer; stdcall;

         {Inline function returns true if Node is a File}
      function IsAFile(  Node : TTreeNode  ) : boolean;
      begin
         Result := ((Node.ImageIndex = IMG_NODE_FILE_CLOSED) or
                    (Node.ImageIndex = IMG_NODE_FILE_OPEN));
      end;

         {Inline function returns true if Node is a Folder}
      function IsAFolder(  Node : TTreeNode  ) : boolean;
      begin
         Result := ((Node.ImageIndex = IMG_NODE_FOLDER_CLOSED) or
                    (Node.ImageIndex = IMG_NODE_FOLDER_OPEN));
      end;


   begin
         {Files before folders}
      if(   IsAFile(  Node1  ) and IsAFolder(  Node2  )   ) then
      begin
         Result := -1;
         Exit;
      end;

         {Folder after file}
      if(   IsAFolder(  Node1  ) and IsAFile(  Node2  )   ) then
      begin
         Result := 1;
         Exit;
      end;

         {Nodes are of the same type, so do a normal alpha sort}
      Result := AnsiStrIComp(  PChar(Node1.Text), PChar(Node2.Text)  );
   end;


Calling the sort routine


   tv_eg5.CustomSort(  @MyCustomSortProc,  0  );


I've added the CustomSort call to the AddNode procedure. This means that every time a node is added the tree is sorted. For this example that is exactly what must happen. If you were loading a tree then you'd only want to sort it once the entire load operation had been completed.






All information on these www pages is copyright (©) 1997 Andre .v.d. Merwe And may not be copied or mirrored without my permission.

1997 Andre .v.d. Merwe And may not be copied or mirrored without my permission.