1

I am trying to change the index of a node, because there are some specific nodes that at all times needs to be at the bottom of my tree. I tried to change the Node.Index, but that did not change anything. So my question is: How do I change the Index of a PVirtualNode?

Thanks! - Jeff

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Jeff
  • 12,085
  • 12
  • 82
  • 152
  • 2
    Are you still storing your data in the *virtual* control or have you taken Rob Kennedy's advice and separated the tree from its data? – David Heffernan Feb 07 '11 at 19:01
  • @David - I don't know how to store the hierarchy in a seperate Data structure, so no. It's the same project aswell. – Jeff Feb 07 '11 at 19:02
  • 1
    Jeff, you said before that you *have no hierarchy*. You just have a list, not a tree. So use an array, or a TList, or a TObjectList, or any other list-like data structure. David and I showed you how to do that, so if you still don't know how, ask about *that*. – Rob Kennedy Feb 07 '11 at 19:28
  • Can someone link to the previous question? – jpfollenius Feb 07 '11 at 22:10
  • @Rob, I have 2 Trees in my project - one which has a hierachy, and one that doesent. – Jeff Feb 08 '11 at 11:15

4 Answers4

4

To change the index of node A, find the node B that has the index you want A to have, and then call Tree.MoveTo(A, B, amInsertBefore, False). B and everything after it will shift down by one to make room for A, and their Index fields will be recalculated. This works even if A doesn't yet exist in the tree (such as just after calling MakeNewNode).

If you're using Index to associate each node with its corresponding data value in a list or array, then you'll find this largely ineffective for re-ordering the displayed values.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • Thanks! So if I was using a different structure, this would not work? – Jeff Feb 07 '11 at 19:33
  • 2
    Jeff, you asked how to change a tree node's Index value, and this is how to do it. It will always work. But if you're using Index to link the tree nodes with your data, then you'll find that it won't have any effect. The data previously displayed for node *B* will now appear with node *A* because *A* has the Index value previously assigned to *B*. So, if you have your data separate from the tree control (as you should), *and* you need to re-order nodes, then don't use the node's Index value to link them together. Use `GetNodeData` instead. (Feel free to post another question about that.) – Rob Kennedy Feb 07 '11 at 19:59
3

You canot change the index of a node. Normally when using VirtualStringTree you hold your data in your own data structure separate from the tree and access the data from the events. You can also store data directly in the nodes (using a record), but I prefer the other approach because it keeps the logic out of the tree view.

For example, you could store the data in a list and access this list in the GetText handler (you can use Node.Index). Then, if you want to reorder the items, just reorder your list and everything else will happen automatically (you might have to call Invalidate on the tree).

Pseudocode:

Initializing:

Tree.RootNodeCount := MyList.Count;

In the GetTextevent:

NodeText := MyList [Node.Index];

Reordering:

Reorder (MyList);
Tree.Invalidate;
jpfollenius
  • 16,456
  • 10
  • 90
  • 156
  • @Smasher - So if I have a hierachy, how would I store that in my own Data structure? I have always stored my stuff in the tree. – Jeff Feb 07 '11 at 19:09
  • 1
    +1 because this should be the way to do it. @Jeff, I'm sure you can handle a "tree" data structure. Just give it 10 minutes, wikipedia is all you need. – Cosmin Prund Feb 07 '11 at 19:11
  • 1
    @Jeff: If you have a hierarchy, why not rebuild this hierachy using classes? You could for example have a `Parent` class that itself contains a list of `Child` classes. The handlers can then get the right data using `Node.Level` and `Node.Index`. This way **model** and **view** are clearly separated. – jpfollenius Feb 07 '11 at 19:12
  • @Smasher - If I create a class, wont I have to do Create/Free for each of them? A minimal example of 2 levels of nodes would be greatly apreciated. However, I don't think I will be doing that for my current project - I wrote over 40 functions and procedures that currently use the Tree to get the data. – Jeff Feb 07 '11 at 19:17
  • @Jeff There are a million examples in Mike Lischke's documentation of the control. There is extensive discussion of the virtual pardigm. – David Heffernan Feb 07 '11 at 19:19
  • 1
    Of course you have to create/destroy them somewhere. But that has nothing to do with the tree view. You would probably load your data from a file and create the hierarchy from that. If you don't want to change this, this is your choice. Just go with the other answers then. But you might want to consider this in your next project. – jpfollenius Feb 07 '11 at 19:21
  • @David - I am having a hard time understanding most of Mike's examples and demos. My buddy taught me to use VirtualStringTree from scratch, and the way I do it now is how I learned it. @Smasher if I have thousands of entries in my structure, and when they are all classes - wont that slow stuff down & consume memory? – Jeff Feb 07 '11 at 19:23
  • 1
    @Jeff: well, you need the memory anyway. Or do you think the data you store in the tree view does not consume memory? Thousands of entries are not a problem at all. This paradigm works with millions of entries without problems. – jpfollenius Feb 07 '11 at 19:26
  • @Jeff I think we are all wasting our breath with this virtual thing. You clearly are entrenched in your current approach. It's not how most of use would do it, but you can get it to work. But you really should bear in mind for the future that there is a better way. Your last two VTV questions demonstrate that, even if you can't see why yet! As for objects slowing things down and consuming too much memory, then no that would not be an issue. – David Heffernan Feb 07 '11 at 19:27
  • @David @Smasher - Dont get me wrong, I want to use it the way you suggest, if I only knew how. I will attempt to do so in my next project. – Jeff Feb 07 '11 at 19:40
2

TVirtualNode is a doubly-linked list, it's not a index-based structure: you change the index of a node by removing it and adding it where you want it.

Look into DeleteNode and AddChild.

Cosmin Prund
  • 25,498
  • 2
  • 60
  • 104
2

Given that you are still using the tree view control as a container, the ideal solution offered by Smasher is not available to you.

One rather obvious solution, given that your tree view has no hierarchy (i.e. it's a list) would be to use the Sort method with your own compare function (OnCompareNodes).

The other blindingly obvious strategy would be to add the node that you want at the bottom last. If you need to add other nodes later, then insert them above the special last node with InsertNode. This simple approach will probably suffice for the problem as you have described it.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490