B4J Question DirectoryChooser & TreeTableView .... how to show a busy indicator witout blocking execution?

Cableguy

Expert
Licensed User
Longtime User
Hi guys,

So, I have a very good looking button that when clicked shows a DirectoryChooser...
The Goal is to List all files and folders starting from what is chosen in the DirectoryChooser, and it works very well, except if I try to select "C:\" as a starting point...
No errors to log, it just freezes and becomes unresponsive.
As I came to understand it, it just take much much time to list it all...
ISo, tried to implement some kind of "busy" indication, but it either blocks the "busy" animation, or the sub just takes way more time to complete..
Here is my sub:
B4X:
Private Sub Button1_Click
    TreeTableView1.Root.Children.Clear
   
    Dim dc As DirectoryChooser
    dc.Initialize
    dc.Title = "Sélectionner un dossier"
   
    'open Last path
    Dim pSaved As String
    If File.Exists(File.DirApp,"path.txt") Then
        pSaved = File.ReadString(File.DirApp, "path.txt")
        dc.InitialDirectory = pSaved
    End If
   
    rootDir  = dc.Show(Main.MainForm)
    If rootDir = "" Then
        Return
    Else
        AddFolder(TreeTableView1.Root, rootDir)
       
        'Save the current Path
        File.WriteString(File.DirApp, "path.txt", rootDir)
    End If
End Sub

Sub AddFolder(Parent As TreeTableItem, Folder As String)
    If File.ListFiles(Folder).IsInitialized = False Then
        Return
    Else
        PathLabel1.Text = "  " & Folder
    End If
    For Each f As String In File.ListFiles(Folder)
        Dim tti As TreeTableItem
        Dim Name As String = f
        Dim Size As String = $"$1.0{File.Size(Folder, f) / 1024} KB"$
        Dim Date As String = $"$DateTime{File.LastModified(Folder, f)}"$
        tti.Initialize("tti", Array(Name, Size, Date))
        Parent.Children.Add(tti)
        If File.IsDirectory(Folder, f) Then
            AddFolder(tti, File.Combine(Folder, f))
            tti.Expanded = False
        End If
    Next

End Sub


How would you suggest I implement this "busy" visual indicator?
(I have tried @Star-Dust Loading indicators, but they either freeze or don't even show)
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
The busy indicator isn't the solution. You are trying to collect all the files and folders. It can take very long time and will surely break at some point.

The wrong solution is to switch to File.ListAsync. The right solution is to implement lazy loading. Only load the folders once the user opens the parent folder.
 
Upvote 0

PaulMeuris

Active Member
Licensed User
Only load the folders once the user opens the parent folder.
Here are some code changes you could apply to load only the files and folders for the selected folder.
The subroutine AddFolder is no longer used as a recursive sub.
In the TreeTableView1_MouseClicked you could drill down the file structure for the items marked as "DIR".
You would have to use some "breadcrumbs" list to allow the user to go back up the tree structure.
Hope this helps a little bit.
B4X:
Sub AddFolder(Parent As TreeTableItem, Folder As String)
    If File.ListFiles(Folder).IsInitialized = False Then
        Return
    Else
'        PathLabel1.Text = "  " & Folder
    End If
    For Each f As String In File.ListFiles(Folder)
        Dim tti As TreeTableItem
        Dim Name As String = f
        Dim Size As String = $"$1.0{File.Size(Folder, f) / 1024} KB"$
        Dim Date As String = $"$DateTime{File.LastModified(Folder, f)}"$
        Dim isdir As String = ""
        If File.IsDirectory(Folder, f) Then isdir = "DIR"
        tti.Initialize("tti", Array(Name, isdir, Folder, Size, Date))
        Parent.Children.Add(tti)
        If File.IsDirectory(Folder, f) Then
'            AddFolder(tti, File.Combine(Folder, f))
            tti.Expanded = False
        End If
    Next
End Sub
Private Sub TreeTableView1_MouseClicked (EventData As MouseEvent)
    Dim ttv As TreeTableView = Sender
    Dim tti As TreeTableItem = ttv.SelectedItem
    Dim fname As String = tti.GetValue(0)
    Dim fldr As String = tti.GetValue(2)
    Log(fname & " " & tti.GetValue(1) & " " & fldr)
    If File.IsDirectory(fldr,fname) = False Then Return
    TreeTableView1.Root.Children.Clear
    lblprogress.Text = "Loading..."
    AddFolder(TreeTableView1.Root, File.Combine(fldr,fname))
    lblprogress.Text = "Finished."
End Sub
 
Upvote 0
Top