How to rapidly stream TTreeView contents

- John Hunt 
- CIS 100343,3317

Bulk operations on a TTreeView are often painfully slow, because every time a
node is referenced using an index, the TTreeView has to walk through its
linked list of nodes to get to the specified index; for bulk operations like
streaming, this can take up a lot of time.

The trick for speeding up such bulk operations is to avoid using indexes to
refer to the TTreeView's nodes. This is simple enough to do when you're
streaming out the contents of the TTreeView - you simply use GetNext to move
from one node to the next while you are streaming. The problem is, how do you
reconstruct the hierarchy of the TTreeView when you stream the data back in?

The solution to this is to precede each node in the stream with an integer
value that denotes that node's relationship to the previous node in the tree.
A node can be related to its previous node in one (and only one) of the 
following ways:

  (1) the node has no previous node (it's the first one in the tree)
  (2) the node is the first child of the previous node 
  (3) the node is the first sibling of the previous node 
  (4) the node is the first sibling of the previous node's parent 
  (5) the node is the first sibling of the previous node's grandparent 
  (6) etc.

By examing the "relational-degree" integer when you stream the node back in,
you can tell where the node needs to be inserted in the TTreeView.

The example program shows how to do this. When the program starts, it creates
ca. 3600 tree nodes containing both some text and some miscellaneous data (a
record that holds four integer values); the nodes are added to the TTreeView
at 4 levels of nesting.

To stream out the TTreeView's contents, press the "Stream to disk" button
(the streamed contents are saved in the file 'treeview.stm' in the current
directory); to read it back it, press the "Read from disk" button; to clear
the list, press the "Clear" button. To test whether the program is really
reconstructing the hierarchy correctly, you can select a node and move the
mouse a little, so that the node goes into editing mode; then you can type
some text into the node. If you then stream the tree view out, clear it, and
stream the tree view back in, you'll notice that your text is just where you
typed it. To view the random data at any node, select the node and then press
the ENTER key; you get a verbalized description of the integers constituting
the data of that node.

When you press the "Stream to disk" button, the program calls the
GetRelToPrev function for each node, which returns an integer denoting the
current node's relationship to its previous node (see the comments under the
function header). That relational-degree integer is then written to the
stream, followed by the node's text and data. To cut down on storage space, I
used a short integer (signed byte) as the relational-degree value; this
allows up to 127 levels of nesting. If you need more levels of nesting, use a
larger-sized integer as the result type of the GetRelToPrev function.

When you press the "Read from disk" button, the relational-degree integer is
read back in for each node, as well as the node's text and data; the node is
then inserted at the proper point in the tree view based on the
relational-degree integer.

Even if you use a different streaming mechanism or model for your TTreeViews,
it should be possible to adapt the above strategy to it so that you obtain
the fastest possible streaming performance.
