B4A Library [Class] Treeview Class (Tree and Node)

After finding how to communicate between classes I improved the previous version and since it is completely different, I opened a new thread for it.

There is a Tree class, in which you have to define the nature of the tree (what database it displays). This class manages the nodes which are defined by another class.

I implemented a horizontal "scroll panel" to compensate for the scrollview's lack of it.

The main is a demo with one tree in portrait and two trees in landscape node.

Edit: Version 3 has automatic setting of the treeview panel height and width, so linewidth is calculated, not supplied.
The datalist is sorted.
Arrows added to the slidepanel to hint about its use.
Edit: version 3 updated to have automatic width reduction when nodes close.
Version 4 can scroll horizontally thanks to Informatix additions.
Edit: version 5 use Informatix new 2D ScrollView.

Edit: Updated to ver. 6 :
- The tree is isolated from the specific use (like file manager or family tree), the definition of the data that populates the nodes is done at the calling activity using sub GetData which is called by the tree when required.( Edit: not all the way, in the node_open you still have to change the tag and the text of the new nodes to suit other kinds of trees...)
- LongClick on a node is passed for action to the calling activity to a sub NodeLongClicked.
- OpenRoot method enables display of the root node open (by code, the user can of course open it by pressing the + button)
- NullImages - Possibility to remove the images of file and folder (the label will move left accordingly).
- Wait cursor activated smartly (!!) only when opening nodes with many children, not to slow the program too much.

Edit: Updated to ver. 7 :
See details in this post. http://www.basic4ppc.com/forum/addi...ss-treeview-class-tree-node-3.html#post149450

Edit: updated to ver. 8, the only change from 7 is that data type is in the tree class , not in the main.
Also the Reflection library is not used and can be ticked off.

Edit: update to ver 9. I saw that with new devices of high resolution the lineheight is too large so I adjusted it to give better results for all devices.
If you encounter line size problems please tell me (with the specific device parameter).

Edit: see post #85 for a method to open all nodes of the tree by code.

Looking forward to get feedback !

Note: For B4A ver. 7 replace in tree line 190 Doevent with sleep(0)
 

Attachments

  • screen3.png
    screen3.png
    58.8 KB · Views: 2,425
  • screen4.png
    screen4.png
    57.7 KB · Views: 2,104
  • Treeview9.1.zip
    24.6 KB · Views: 548
Last edited:

Informatix

Expert
Licensed User
The treeview is ScrollView2D, maybe here the troble root is...
I have the same problem because there's a mistake in the Tree module at line #33. Remove the line:
treeview.Panel.Initialize("")
The inner panel should never be initialized by the user.
 

Franco Scotuzzi

New Member
Licensed User
Hi ,
thank's for this fantastic class.

Is possible to open ALL node by software ?

I tryed a lot but whit no result.

thanks.
 

derez

Expert
Licensed User
Hi ,
thank's for this fantastic class.

Is possible to open ALL node by software ?

I tryed a lot but whit no result.

thanks.
If you add the following code to the tree class you can open all nodes using tree.OpenAllNodes instead of tree.OpenRoot :
B4X:
public Sub OpenAllNodes
    OpenRoot
    OpenAll(rootnode)
End Sub

Private Sub OpenAll(tnn As Node)
    For Each tnn As Node In tnn.TN.children
        If tnn.TN.Btn.Tag Then
            Node_Open(tnn)
            tnn.TN.Btn.SetBackgroundImage(LoadBitmap(File.DirAssets,"minus2.png"))
            tnn.TN.Btn.tag = False
            OpenAll(tnn)
        End If
    Next
End Sub

I have a crash when closing "data" node but it does not happen when closing from low level up , I don't know why.
I believe it is related to memory problems, it happens with another application with a different database as well.
 
Last edited:

derez

Expert
Licensed User
I have improved the above by adding depth value in the OpenAllNodes method.
Now you can decide how much of the tree you want to open at once.
B4X:
public Sub OpenAllNodes(depth As Int)
    OpenRoot
    OpenAll(rootnode, depth)
End Sub

Private Sub OpenAll(tnn As Node, depth As Int)
    If tnn.TN.level > depth Then Return
    For Each tnn As Node In tnn.TN.children
        If tnn.TN.Btn.Tag Then
            tnn.TN.Btn.SetBackgroundImage(LoadBitmap(File.DirAssets,"minus2.png"))
            tnn.TN.Btn.tag = False
            Node_Open(tnn)
            OpenAll(tnn, depth)
        End If
    Next
End Sub
 

JOTHA

Well-Known Member
Licensed User
Hello derez,

thank you for sharing this really excellent code!

But if I want to decide how much of the tree I want to open at once, it doesnt work.

I have improved the above by adding depth value in the OpenAllNodes method.
Now you can decide how much of the tree you want to open at once.
B4X:
public Sub OpenAllNodes(depth As Int)
    OpenRoot
    OpenAll(rootnode, depth)
End Sub

Private Sub OpenAll(tnn As Node, depth As Int)
    If tnn.TN.level > depth Then Return
    For Each tnn As Node In tnn.TN.children
        If tnn.TN.Btn.Tag Then
            tnn.TN.Btn.SetBackgroundImage(LoadBitmap(File.DirAssets,"minus2.png"))
            tnn.TN.Btn.tag = False
            Node_Open(tnn)
            OpenAll(tnn, depth)
        End If
    Next
End Sub

In the main I use this code:
B4X:
    tree2.OpenAllNodes(15)

In this example I want to open 15 nodes, but only the first node is opened.
I have 23 files in the tree ... it is equal how much I write in the code, always it opens just the first node ...
How to open all nodes, how could I know how much files I will have?
Is it possible to know that before and get the value before opening the nodes?
 

derez

Expert
Licensed User
Hello derez,

thank you for sharing this really excellent code!

But if I want to decide how much of the tree I want to open at once, it doesnt work.



In the main I use this code:
B4X:
    tree2.OpenAllNodes(15)

In this example I want to open 15 nodes, but only the first node is opened.
I have 23 files in the tree ... it is equal how much I write in the code, always it opens just the first node ...
How to open all nodes, how could I know how much files I will have?
Is it possible to know that before and get the value before opening the nodes?
This is a class, so you can run it in debug mode and see where and why it stops the process of opening nodes.
the application does not know what is inside a node until it opens it.
The depth value is the number of levels, not the number of items in the node.

(Have you copied the code from my last post or only the command tree2.OpenAllNodes(15) ?)
 
Last edited:

JOTHA

Well-Known Member
Licensed User
Hello derez,

thank you for your fast answer.
I've copied the code in post #86 where you said: "I have improved the above by adding depth value in the OpenAllNodes method".

I will try to use your solution to read a structure from a SQLite-Database, but first I have to play arround with folders to understand your solution ...
 

JOTHA

Well-Known Member
Licensed User
Hello derez,

now I have written the code into the Sub Activity_Resume and it works ... and it opens one Level with tree2.OpenAllNodes(0)
maybe it is index-based ... thank you for your advice!
 

JOTHA

Well-Known Member
Licensed User
Hello derez,

one more question:
How can I create this "old-style-design" for a tree like you can see in the attached picture?
I mean the lines on the levels ...

Tree-Lines.png

I know, it must be done with images, bitmaps ... but how can I put them into the different places on the levels?

Thank you again in advance!
 

derez

Expert
Licensed User
Hello derez,

one more question:
How can I create this "old-style-design" for a tree like you can see in the attached picture?
I mean the lines on the levels ...

View attachment 52701
I know, it must be done with images, bitmaps ... but how can I put them into the different places on the levels?

Thank you again in advance!
The lines that appear between the nodes are entities that belong to more than one node so at first look it seems to me hard to achieve without making a big mess in the class.
I'll think about it but can't promise anything.
Maybe the solution is in some other ready-made tree structure.

How is the line defined ? going from a node to ?
 
Last edited:

JOTHA

Well-Known Member
Licensed User
The lines that appear between the nodes are entities that belong to more than one node so ...

Hi derez,

I was thinking about that will be difficult ... but you did great work until to this point!

Please let me ask another question:
How can I add one or more images to the place where the image with the folder is?
I mean to add a image on the same place before or after the folder image ... is it possible or is it also a lot of work?

Many Thanks!
 

derez

Expert
Licensed User
Hi derez,

I was thinking about that will be difficult ... but you did great work until to this point!

Please let me ask another question:
How can I add one or more images to the place where the image with the folder is?
I mean to add a image on the same place before or after the folder image ... is it possible or is it also a lot of work?

Many Thanks!
Please answer this : How is the line defined ? going from a node to ?

The folder image is used in the file manager tree, you can replace it by aby other image, for example in a family tree I use the picture of the person who is represented by the node.
If you want more pictures you have two options:
1. follow the definitions of img in the node and tree classes and add another image with different name, while making room for it in the node (move the label).
2. Combine all the images to create one picture and place it in the node instead of the original img. You'll have to move the label to make room here also.

upload_2017-2-9_12-51-38.png
 

JOTHA

Well-Known Member
Licensed User
Please answer this : How is the line defined ? going from a node to ?

The folder image is used in the file manager tree, you can replace it by aby other image, for example in a family tree I use the picture of the person who is represented by the node.
If you want more pictures you have two options:
1. follow the definitions of img in the node and tree classes and add another image with different name, while making room for it in the node (move the label).
2. Combine all the images to create one picture and place it in the node instead of the original img. You'll have to move the label to make room here also.

View attachment 52718
Hi derez,

I made nearly the same, but instead of the photos I added the level as a image with numbers (see attached screenshot):
Screenshot Ausschnitt.png


Also the code with different colors works good!

Now I want to add a information ich which I can see how much folders are in the different levels.
That means: I want to add an image with this information before or behind the image with the level ...

So I have to try to go the "way No 1" ...

By the way: How did you create the round corners?
 

derez

Expert
Licensed User
In node class in initialization sub there is a line "TN.lbl.color = LabelColor"
Change this line to "TN.lbl.Background = " with a color drawable with round corners and your color.
 

JOTHA

Well-Known Member
Licensed User
... and your color.
... that means there is no way to change the color of the background (I see in your example you have only one background color) ?
 

derez

Expert
Licensed User
... that means there is no way to change the color of the background (I see in your example you have only one background color) ?
Labelcolor is a parameter in the initialization of each node so you can define for each node a different color (create a drawable with labelcolor as its color).
 

JOTHA

Well-Known Member
Licensed User
Thank yo for teaching me ... its a little bit complicated but I'll try it again tomorrow.
 

derez

Expert
Licensed User
Thank yo for teaching me ... its a little bit complicated but I'll try it again tomorrow.
Not at all. Change in node class like this:
B4X:
Sub Initialize(Module As Tree, _
...

TN.lbl.Text = Text
TN.lbl.TextSize = TextSize
TN.lbl.TextColor = TextColor
'TN.lbl.color = LabelColor
Dim cdr As ColorDrawable
cdr.Initialize(LabelColor, 0.1*lh)
TN.lbl.Background = cdr

...
End Sub

When you initialize a node in tree class (in sub node_open) set labelcolor to the color you want.
 
Top