revUp - Updates and news for the LiveCode community
Issue 113 | July 1st 2011 Contact the Editor | How to Contribute

rTree 2.0
A review of this upcoming new release to our popular third party tree control addon for LiveCode

by Malte Pfaff-Brill

Summer is here, the trees are in blossom. Today is a good day, as I have the opportunity to write about a superb add-on to the LiveCode development environment. Before I start I'd better introduce myself. My name is Malte Pfaff-Brill, I am the CEO of a IT-service agency in the most northern part of Germany.

If you are a fellow LiveCode developer, you might think there is that Multimedia guy again, boasting about his library animationEngine. Well that is not the case this time. Today I want to take the pleasure to tell you about an add-on to LiveCode I did not write myself. The library I am writing about is rTree by TapirSoft. You might have stumbled upon it already in the LiveCode marketplace. However I am writing about a version you will not have seen before. It is the brand new version 2.0, due out next week*.

Why does this one get me excited so much?

I have been developing software for archaeologists, called archaeoDox. One of the crucial elements in this software is a tree control, which is constantly updated. For version one of archaeoDox, my company was using Data Tree, which covered our basic needs quite nicely. My company is pretty experienced with using tree controls in LiveCode, so we know the other libraries that are around too. We have also been consulting for a company using the iMedTree library, which seems no longer to be actively maintained. All of the projects we have been working on that need a tree control are pretty complex. They need to display many trees, each rendering thousands of nodes. And this is where it gets tricky.

Yesterdays problems
When you are working on a tree that displays that many nodes it gets slow. Terribly slow. Performance suffers exponentially when thousands of nodes are rendered. This is true for both the initial rendering of all nodes and also when collapsing or expanding a node. If you have very many nodes to display each library suffers the same problem. Refreshing the screen could take up to 6 seconds in a worst case scenario. I have discussed this issue a lot with Mats Wilstrand, the developer of rTree. I asked him why every library always draws all nodes, no matter if they are visible or not, instead of only drawing the visible nodes and caching the rest, just like the datagrid does. He jumped on it. It took a couple of days and I had a preview version of rTree that does exactly that!

Starting the benchmark tests
Now I was curious. I had to test if this really boosts performance and the results were overwhelming. My worst case scenario (6 seconds to render the tree I wanted to display) now was drawn in under 300 milliseconds! Very, very cool! So now that is a non issue. rTree really only draws the nodes that are visible on screen. Awesome! But it does not stop here.

Nodes are controls!
Being blown away by the performance I was lucky enough to have the time to look at the extra goodies rTree has to offer. At this point I am unable to say what stuns me most. Each node can not only carry icons and a label, you can even style each node individually. You can set text colors and sizes. You can even define custom properties for a node. Basically you can use anything you are used to from LiveCode controls on a node. Way to go! Next I want to focus on two of the things that impressed me most - sublines and badges.

Sublines
Ever ran into a situation where you wanted to display additional info on a tree node without the need to click it? Maybe a warning that the data associated with that node is incomplete? I certainly have. I always longed for a way to give warnings right inside the tree. But using the nodes label is a suboptimal solution. rTree to the rescue! It can display additional lines of text in a node by simply setting a property (or, if you are like me, feeding the data from an array)

Badges
Another really cool feature is badges. Each node can display a badge on the right side of the nodeLabel to give additional info, like for example the number of children of a parent node. This really helped in archaeoDox to gain an even better overview of the data being processed.

How does that beast work?
Most of the time setting up a library for use in your own project is a little complicated. Well, Mats took care of that with the excellent rTree workbench. It is packed with code examples on tree usage. You should take a little time to explore the demo scripts and read up on the general concepts. After having done that, you are good to go. If you are starting a fresh project, you can use the wizard Mats has set up to create an initial tree on a blank stack. Just hit the button and you are ready to go. There is also a method that lets you create a new tree from scratch with just a single line of code:

create_rTree "myTree"

Simple as that.

Not in the mood for scripting?
You can also use the wizard, to copy a tree control to an existing stack (and copy over all necessary elements, like the rTreeEngine library). Of course, if you want to, you can do all this manually and take complete control over the necessary steps.

What takes a little bit of getting used to is the behavior when you are resizing the tree control with the pointer tool. The first time you resize the tree using the pointer tool, it looks a little bit like there would be wonky things happening. It does not, as the tree control takes care of its geometry, even when resizing it in edit mode. No need to be scared.

Clever, clever, clever!
Impressive work on the usability part of rTree. Once a tree control is set up (technically this is just a group), you can just use it. No need to start using the library in your script. Nada. The control gets a behavior set, which takes care of all the initialization needed. (I hope Mats will not mind me taking up this idea for animationEngine in a later release). Well done. Once set up (and given the rTreeEngine is in memory) it will take care of itself. That is what I would call writing user friendly components!

Handlers or array, the choice is up to you
You can start working with your tree, using a rich set of handlers to create and delete nodes and do all sorts of things you'd expect from a tree library. Most functionality like drag and drop or context menus come out of the box. Each part can be customized to your liking. It is the complete opposite of what you are used to in coding. It takes more work to turn off features than implementing them!

Let me show you an example of how a tree is created using rTrees handlers:

Here comes a recipe for creating 1100 nodes 3 levels deep and Windows style using commands and setting properties.

on mouseUp
   lock messages
   # Clear all data from the Tree.
   dispatch "delete_treeData" to control "Tree"
   # Set icons at Tree level.
   set the firstIconCollapsed of control "Tree" to 2194
   set the firstIconExpanded of control "Tree" to 2195
   set the secondIconCollapsed of control "Tree" to 2198
   set the secondIconExpanded of control "Tree" to 2197
   # Create new Nodes via commands and setting Node properties.
   repeat 10 times
      dispatch "new_node" to control "Tree"
      get the lastNodeID of control "Tree"
      set the depth_of_node_ID_[it] of control "Tree" to 0
      repeat 10 times
         dispatch "new_node" to control "Tree"
         get the lastNodeID of control "Tree"
         set the depth_of_node_ID_[it] of control "Tree" to 1
         repeat 10 times
            dispatch "new_node" to control "Tree"
            get the lastNodeID of control "Tree"
            set the depth_of_node_ID_[it] of control "Tree" to 2
         end repeat
      end repeat
   end repeat
   # Render the Tree.
   dispatch "renderTree" to control "Tree"
   unlock Messages
end mouseUp

However, if you work in more complex environments, your data might not lend its hand to work like that. Most of the time I tend to be using arrays to build the tree. A little demo Script using array notation looks like this:


local sTreeArray
on mouseUp
   dispatch "delete_nodeData" to control "tree"
   set the rootNodeIDs of control "Tree" to 1
   refreshtree
   set the nodeData of control "Tree" to sTreeArray -- tA
   dispatch "renderTree" to group "Tree"
end mouseUp
on refreshtree pNode
   put "Root" into sTreeArray[1]["label"]
   put "test1" into sTreeArray[2]["label"]
   put "test2" into sTreeArray[3]["label"]
   put "test3" into sTreeArray[4]["label"]
   put 2&cr&3&cr&4 into sTreeArray[1]["children"]
   put "childOf3-1" into sTreeArray[5]["label"]
   put "childOf3-2" into sTreeArray[6]["label"]
   put "childOf3-3" into sTreeArray[7]["label"]
   put 5&cr&6&cr&7 into sTreeArray[4]["children"]
   put "ChildOf1-1" into sTreeArray[8]["label"]
   put "ChildOf1-2" into sTreeArray[9]["label"]
   put "ChildOf1-3" into sTreeArray[10]["label"]
   put 8&cr&9&cr&10 into sTreeArray[2]["children"]
   put "childOf1-1-1" into sTreeArray[11]["label"]
   put "childOf1-1-2" into sTreeArray[12]["label"]
   put "childOf1-1-3" into sTreeArray[13]["label"]
   put 11&cr&12&cr&13 into sTreeArray[8]["children"]
   put "Sublines test" &cr& "Second line" into \
          sTreeArray[1]["sublines"]
   put "red" into sTreeArray[1]["textColor of line 1 of the \
          sublines"]
   put "blue" into sTreeArray[1]["textColor of line 2 of the \
          sublines"]
   put true into sTreeArray[5]["visible of the badge"]
   put "Malte" into sTreeArray[5]["label of the badge"]
end refreshtree

Right now we are in a transitional stage where we move archaeoDox from dataTree to rTree. The transition is fun and the new feature set is well worth the effort.

rTree 2.0 will be available soon. If you need a Tree control you should hurry, as there is a very interesting offer that can save you some pennies.

*rTree 2.0 is expected out within a week or two. Any purchasers of this great marketplace addon before the release of 2.0 will automatically be upgraded to 2.0 for free. Version 2.0 will be increasing in price to $79, so this represents a substantial saving on getting this fabulous time and effort saving tree control. It is also a part of our 3 for 2 Marketplace offer during July. So buy early and save twice!

About the Author

Malte Brill is long time LiveCode User and Marketplace pioneer. CEO of derbrill Multimedia and CTO of awesomemegamightygames.

 

Main Menu

What's New

Marketplace three for two during July