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.b4x.com/forum/additional...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,886
  • screen4.png
    screen4.png
    57.7 KB · Views: 2,523
  • Treeview9.1.zip
    24.6 KB · Views: 867
Last edited:

derez

Expert
Licensed User
Longtime User
The real reason I added the sort is that I used "android" directory a lot while testing the scroll, because it has long names underneath and I didn't want to scroll down much...

The only interface for date is the get_data sub, the main needs only to launch the tree and define its properties. I could transfer this sub to the main (in order to have a stand-alone tree class) but it required to pass the name of the launching module and to my taste isn't necessary, as the code of the class is open and for sure is going to be modified by the developer anyhow.
Sort is part of this sub so it should be included in the adaptation.

As I understand the use of the tree - it is for display of existing database of some kind. I fail to see why you need to change the content of the tree and not change the database which it is based on.

Besides, you and me know what to do, and it seems that nobody else is interested...
 
Last edited:

Informatix

Expert
Licensed User
Longtime User
As I understand the use of the tree - it is for display of existing database of some kind. I fail to see why you need to change the content of the tree and not change the database which it is based on.
You change them both. I talked about different kinds of tree (which need different layouts, different data, but same logic: it's still a tree with nodes).

I just published a library "ScrollView2D" based on a source code I found on the net. It's even better than everything we did until now.
 

derez

Expert
Licensed User
Longtime User
I talked about different kinds of tree (which need different layouts, different data, but same logic: it's still a tree with nodes).

Can you give an example of such ?
 

derez

Expert
Licensed User
Longtime User
Updated to ver. 7

The class is completely independent from the specific task of the tree - see the pictures ( in the first post http://www.b4x.com/forum/additional...lass-treeview-class-tree-node.html#post109757) of file manager and family tree - using the same class.

A capability to put a specific image for each node, or use common bitmaps is added.
A better control of the label and text colors - introducing two sets that can be predefined and switched for each node, see the demo program and the file manager picture there.

The calling activity needs the following:
dim a tree
create Type data(...) like in the demo - no need, it is in the tree class.
initialization of tree.
Add_view to the parent (activity or panel)
Set_root
optional - OpenRoot
Sub called GetData (serving the tree's Node_Open sub, to supply task specific data for the new nodes)
Sub called NodeLongClicked

Ready for questions and comments :)
 
Last edited:

Suntzu

Member
Licensed User
Longtime User
Thank you! I will try to incorporate this with my current code and give you a feedback.

Sent from my SAMSUNG-SGH-I717
 

onikudaki

Member
Licensed User
Longtime User
question

Hi Derez,

just trying to use the version 7 of your tree/node classes and my compiler is complaining -

Error description: Unknown type: scrollview2d
Are you missing a library reference?


should I be downloading the scrollview2d libs as well ?

otherwise, it looks like this is a perfect solution to a problem i'm having

thanks for the good work :)
 

onikudaki

Member
Licensed User
Longtime User
Aha, I've sorted it thanks, just needed the libs and am away :eek:

just gotta work through the logic of not doing a file explorer type app now.

thanks again for the excellent class
 

alienhunter

Active Member
Licensed User
Longtime User
Thanks
for this excellent Class
i got 3 windows open and still smooth
very good work

AH
 

Attachments

  • 102.jpg
    102.jpg
    71.6 KB · Views: 352

Mashiane

Expert
Licensed User
Longtime User
Hi, cool class indeed. Can you share the code for your family tree please. Is it linked to a database table or hard coded? How can I use your example to read node information from a table and load it? Maybe your family tree example will provide some light as the attached example of v7 deals only with files and folders read from a device? Thanks.
 

derez

Expert
Licensed User
Longtime User
Can you share the code for your family tree please. Is it linked to a database table or hard coded? How can I use your example to read node information from a table and load it?

1. The application has access to parse so I don't want to share it, but I'm ready to give parts of it and help with specific code.
The app uses a sqlite database (actually started with a simple array but then translated everything to use SQLite)
Attached find the sub which gets the data for the tree. There are to types of trees, one for the person's roots (ancestors) and the other for his/her offsprings.
Fcod is the father ID number, Mcod - the mother's ID, Scod - the spouse ID. The first part is relatively simple - it takes the Fcod and the Mcod directly from the person's line. The second part finds children so the select string has to find all the people that has the person's ID as their Fcod or their Mcod.
The photos for the thumbnails are kept in a jpg directory with the name <id>.jpg .
If more explanations are needed - let me know.


B4X:
Sub GetData(tr As Tree, st As String) 'ignore
Dim k, ColorSet, P_id(2) As Int 'ignore
Dim str, Tag,Text,BtnTag As String 'ignore
k = st
If treeflag Then                                      ' root
    cur = SQL.ExecQuery2("SELECT Fcod, Mcod FROM FTable WHERE No = ?",Array As String(k))
    cur.Position = 0
    P_id(0) = cur.GetInt("Fcod")
    P_id(1) = cur.GetInt("Mcod")
    For j = 0 To 1
        Dim da As Data
        If P_id(j) > 0 Then
            da.Tag = P_id(j)
            If relpnl.Visible AND check_rlist(P_id(j)) Then
                da.ColorSet = 1
            Else
                da.ColorSet = 0
            End If
      
            cur = SQL.ExecQuery2("SELECT Surname, Name, Fcod, Mcod FROM FTable WHERE No = ?",Array As String(P_id(j)))
            cur.Position = 0
            da.Text = cur.GetString("Surname")& " " & cur.GetString("Name")
      
            If cur.GetInt("Fcod") > 0 OR cur.GetInt("Fcod")>0 Then
                da.BtnTag = True
            Else
                da.BtnTag = False
            End If
      
            If File.Exists(File.DirRootExternal & "/Family/jpg",P_id(j) & ".jpg") Then
                da.imgflag = 3
                da.imgdir = File.DirRootExternal & "/Family/jpg"
                da.imgfile = P_id(j) & ".jpg"
            Else
                da.imgflag = 0
            End If
      
            tr.DataList.Add(da)
        End If
    Next
Else                                                    ' tree
    Dim cur1 As Cursor
    Dim kk, scod As Int
    cur = SQL.ExecQuery2("SELECT No,Surname,Name,Scod FROM FTable WHERE Fcod = ? OR Mcod = ?",Array As String(k,k))
    If cur.RowCount > 0 Then
        For i = 0 To cur.RowCount - 1
            Dim da As Data
            cur.Position = i
            kk = cur.GetInt("No")
            scod = cur.GetInt("Scod")
            da.Tag = kk
            If relpnl.Visible AND check_rlist(kk) Then da.ColorSet = 1 Else da.ColorSet = 0
            If scod > 0 Then
                da.Text = cur.GetString("Surname") & " " & cur.GetString("Name") & " + " & Get_Name(scod)
            Else
                da.Text = cur.GetString("Surname") & " " & cur.GetString("Name")
            End If
            cur1 = SQL.ExecQuery2("SELECT No FROM FTable WHERE Fcod = ? OR Mcod = ?",Array As String(kk,kk))
            If cur1.RowCount > 0 Then
                da.BtnTag = True
            Else
                da.BtnTag = False
            End If
      
            If File.Exists(File.DirRootExternal & "/Family/jpg",kk & ".jpg") Then
                da.imgflag = 3
                da.imgdir = File.DirRootExternal & "/Family/jpg"
                da.imgfile = kk & ".jpg"
            Else
                da.imgflag = 0
            End If
            tr.DataList.Add(da)
        Next
    End If
End If
End Sub
 
Last edited:

derez

Expert
Licensed User
Longtime User
Updated to ver. 8, data type moved to the tree class from the main.
 

padvou

Active Member
Licensed User
Longtime User
Dear Derez,
how about clicking and not longclicking a node?

Main:
B4X:
Public Sub NodeClicked(tr As Tree,st As String)
Msgbox("Use it to do something in the tree instead of this msgbox", "click")
End Sub

Tree:
B4X:
Sub Node_Click(tnode As Node)
If SubExists(MyModule,"NodeClicked") Then
    CallSubDelayed3(MyModule,"NodeClicked",Me,tnode.TN.tag)
End If
End Sub

Node:
B4X:
Private Sub lbl_click
    Cmodule.Node_Click(Me)
End Sub
 
Last edited:

padvou

Active Member
Licensed User
Longtime User
After the activity is paused and resumed, the tree is no longer expanded. However, when the application starts the first time, it expands the tree. How could we keep the tree opened after resume?
 

derez

Expert
Licensed User
Longtime User
how about clicking and not longclicking a node?
The code in Node is this:
B4X:
Private Sub lbl_click
'    Cmodule.Node_Click(Me)
End Sub

Private Sub lbl_longclick
    Cmodule.Node_longClick(Me)
End Sub
You can use the lbl_click to call Tree instead of longClick. I used longclick because while moving the tree (scrollview) you may hit a label which will be interpreted as a click.

when the application starts the first time, it expands the tree
In activity_resume there is OpenRoot command, which opens the first level. It happens when resuming the activity.
More expansion is only by the user.
 
Last edited:

padvou

Active Member
Licensed User
Longtime User
You can use the lbl_click to call Tree instead of longClick. I used longclick because while moving the tree (scrollview) you may hit a label which will be interpreted as a click.


In activity_resume there is OpenRoot command, which opens the first level. It happens when resuming the activity.
More expansion is only by the user.[/quote]

It's called and I also call it in various places during runtime, however it's not opened.
 

derez

Expert
Licensed User
Longtime User
You'll have to show [parts of ] the code to see what is wrong in your program.
With the demo program it works for tree2 which is called in activity_resume.
 

padvou

Active Member
Licensed User
Longtime User
Here you are:
B4X:
tree2.ClearTree
tree2.setRoot(File.DirRootExternal & "/machines/","TreeTitle",0,bmp)
tree2.OpenRoot
This code is executed at runtime, but it does not expand the tree. Is the tree filled async?
 
Top