Macros/ScriptForge/TreeControlExample-bis
Appearance
< Macros | ScriptForge
TDF LibreOffice Document Liberation Project Community Blogs Weblate Nextcloud Redmine Ask LibreOffice Donate
How to display data in a tree control
(The less easy way)
Authored by Jean-Pierre Ledure.
Navigate through hierarchical data by means of a tree control. Why the less easy way?
When the number of sublevels is undefined and/or when the number of sub-nodes can be huge, the data is better grabbed each time any expand icon is pressed. The technique is illustrated with a customized file picker.

How to run it in BASIC
Create a new document.
- Open the Basic IDE
- Select the first available blank module
- Copy and paste the Basic code
- Verify lines 12-13
- Configure in line 18 the top folder of the file picker in the usual system notation
- Run Main()
How to run it in Python
Create a new document.
- Run APSO
- Create a new module, call it 'Module1'
- Copy and paste the Python code below
- Verify lines 15-16
- Set in line 21 the top folder of the file picker in the usual system notation
- Save and run the Main() method
Code
REM SCRIPTFORGE WIKI EXAMPLE
REM How to animate a tree control like a file picker ?
REM Minimal required version: LibreOffice 7.6
REM Used services
REM SFDialogs.Dialog, SFDialogs.DialogControl, ScriptForge.FileSystem, ScriptForge.Array
Option Explicit
'*******************************************************************
'*** Adjust module name if not "Module1"
'*******************************************************************
Const onnodeselected = "vnd.sun.star.script:Standard.Module1.TreeSelected?language=Basic&location=document"
Const onnodeexpanded = "vnd.sun.star.script:Standard.Module1.TreeExpanded?language=Basic&location=document"
'*******************************************************************
'*** Set the starting folder of the file picker
'*******************************************************************
Const startfolder = "/opt/libreoffice24.2"
'*******************************************************************
'* Run the demo below
'*******************************************************************
Sub Main(Optional event As Object)
Dim dialog As Object ' The SFDialogs.Dialog object
GlobalScope.BasicLibraries.loadLibrary("ScriptForge")
Set dialog = SetupDialog()
InitTree(dialog)
dialog.Execute()
dialog.Terminate()
End Sub
'*******************************************************************
'* Specific demo code
'*******************************************************************
Sub InitTree(ByRef dialog As Object)
' Initialize the tree with the root node, i.e. an arbitrary folder
Dim treecontrol As Object ' A SFDialogs.DialogControl service instance
Dim rootnode As Object ' com.sun.star.awt.tree.XTreeNode
treecontrol = dialog.Controls("FilePicker")
' Each node will contain - a DisplayValue = last path component
' - a DataValue = the full path
Set rootnode = treecontrol.CreateRoot(displayvalue := startfolder, datavalue := startfolder)
SetSubtree(treecontrol, rootnode)
' Activate the node selection and expansion triggers
treecontrol.OnNodeSelected = onnodeselected
treecontrol.OnNodeExpanded = onnodeexpanded
End Sub
'*******************************************************************
'* Fired when an item in the tree control is selected
'*******************************************************************
Sub TreeSelected(Optional event As Variant)
' Triggered by the OnNodeSelected event
Dim dialog As Object ' The SFDialogs.Dialog object
Dim treecontrol As Object ' A SFDialogs.DialogControl service instance
Dim node As Object ' com.sun.star.awt.tree.XTreeNode
Dim textbox As Object ' A SFDialogs.DialogControl service instance
Dim fullpath As String ' A file or folder name
Dim fso As Object ' The ScriptForge.FileSystem service unique instance
If IsNull(event) Then Exit Sub
Set treecontrol = CreateScriptService("DialogEvent", event)
Set dialog = treecontrol.Parent
' Display the content of the selected node when it is not expandable
Set node = treecontrol.CurrentNode
fullpath = node.DataValue
Set textbox = dialog.Controls("FileDetails")
Set fso = CreateScriptService("FileSystem")
fso.FileNaming = "SYS" ' Only use the system file notation
If fso.FolderExists(fullpath) Then
textbox.Value = "FOLDER: " & fullpath
ElseIf fso.FileExists(fullpath) Then
textbox.Value = "FILE: " & fullpath _
& Chr(10) & "Length: " & Split(fso.GetFileLen(fullpath), ".")(0) & " bytes" _
& Chr(10) & "Modified on: " & fso.GetFileModified(fullpath)
End If
End Sub
'*******************************************************************
'* Fired when an item in the tree control is expanded
'*******************************************************************
Sub TreeExpanded(Optional event As Variant)
' Triggered by the OnNodeExpanded event
Dim treecontrol As Object ' A SFDialogs.DialogControl service instance
Dim node As Object ' com.sun.star.awt.tree.XTreeNode
If IsNull(event) Then Exit Sub
Set treecontrol = CreateScriptService("DialogEvent", event)
Set node = event.Node
If node.ChildCount > 0 Then Exit Sub ' The node was expanded previously, do nothing
SetSubtree(treecontrol, node)
End Sub
'*******************************************************************
'* Subfolders and subfiles
'* Called when root is created or when a folder is expanded
'*******************************************************************
Sub SetSubtree(treecontrol As Object, node As Object)
' Find all folders and files depending on the given node of the given treecontrol
' Sort them, folders first
' Add as subnodes all folders and files to the given node
Dim folder As String ' The folder represented by the fiven node
Dim subfiles As Variant ' Array of files in the current folder
Dim subfolders As Variant ' Array of subfolders in the current folder
Dim subitems As Variant ' Array aggregating subfolders and subitems
Dim fso As Object ' The ScriptForge.FileSystem service unique instance
Dim arr As Object ' The ScriptForge.Array service unique instance
Dim s As String ' Loop variable
Set fso = CreateScriptService("FileSystem")
fso.FileNaming = "SYS" ' Only use the system file notation
Set arr = CreateScriptService("Array")
folder = node.DataValue
If Not fso.FolderExists(folder) Then Exit Sub ' The node is not a folder, exit
' Collect all subfolders and files contained below the node argument
subitems = fso.SubFolders(folder)
If UBound(subitems) < 0 Then subfolders = Array() Else subfolders = arr.Sort(subitems, CaseSensitive := False)
subitems = fso.Files(folder)
If UBound(subitems) < 0 Then subfiles = Array() Else subfiles = arr.Sort(subitems, CaseSensitive := False)
subitems = arr.Flatten(arr.Append(subfolders, subfiles))
' Build the next level of the tree under the current node
For Each s In subitems
treecontrol.AddSubNode(node, displayvalue := fso.GetName(s), datavalue := s)
Next s
End Sub
'*******************************************************************
'* May be defined with the Basic IDE
'*******************************************************************
Function SetupDialog()
' Build from scratch the example dialog and its controls
Dim dialog As Object ' The SFDialogs.Dialog object
Dim control As Object ' A SFDialogs.DialogControl object
Set dialog = CreateScriptService("NewDialog", "Tree", Array(115, 65, 260, 217))
dialog.Caption = "File picker"
With dialog
' The close button
Set control = .CreateButton("CloseButton", place := Array(230, 207, 30, 12), push := "OK")
control.Caption = "Close"
' The tree control
Set control = .CreateTreeControl("FilePicker", place := Array(10, 6, 245, 160))
' The textbox with the details
Set control = .CreateTextField("FileDetails", place := Array(10, 170, 245, 33), multiline := True)
End With
Set SetupDialog = dialog
End Function
# coding: utf-8
from __future__ import unicode_literals
# SCRIPTFORGE WIKI EXAMPLE
# How to animate a tree control like a file picker ?
# Minimal required version: LibreOffice 7.6
# Used services
# SFDialogs.Dialog, SFDialogs.DialogControl, ScriptForge.FileSystem
from scriptforge import CreateScriptService
# *******************************************************************
# *** Adjust module name if not 'Module1'
# *******************************************************************
onnodeselected = 'vnd.sun.star.script:Module1.py$TreeSelected?language=Python&location=document'
onnodeexpanded = 'vnd.sun.star.script:Module1.py$TreeExpanded?language=Python&location=document'
# *******************************************************************
# *** Set the starting folder of the file picker
# *******************************************************************
startfolder = '/opt/libreoffice24.2'
# *******************************************************************
# * Run the demo below
# *******************************************************************
def Main(event = None):
# dialog The SFDialogs.Dialog object
dialog = SetupDialog()
InitTree(dialog)
dialog.Execute()
dialog.Terminate()
# *******************************************************************
# * Specific demo code
# *******************************************************************
def InitTree(dialog = None):
# Initialize the tree with the root node, i.e. an arbitrary folder
# treecontrol A SFDialogs.DialogControl service instance
# rootnode com.sun.star.awt.tree.XTreeNode
treecontrol = dialog.Controls('FilePicker')
# Each node will contain - a DisplayValue = last path component
# - a DataValue = the full path
rootnode = treecontrol.CreateRoot(displayvalue = startfolder, datavalue = startfolder)
SetSubtree(treecontrol, rootnode)
# Activate the node selection and expansion triggers
treecontrol.OnNodeSelected = onnodeselected
treecontrol.OnNodeExpanded = onnodeexpanded
# *******************************************************************
# * Fired when an item in the tree control is selected
# *******************************************************************
def TreeSelected(event = None):
# Triggered by the OnNodeSelected event
# dialog The SFDialogs.Dialog object
# treecontrol A SFDialogs.DialogControl service instance
# node com.sun.star.awt.tree.XTreeNode
# textbox A SFDialogs.DialogControl service instance
# fullpath A file or folder name
# fso The ScriptForge.FileSystem service unique instance
if event is None:
return
treecontrol = CreateScriptService('DialogEvent', event)
dialog = treecontrol.Parent
# Display the content of the selected node when it is not expandable
node = treecontrol.CurrentNode
fullpath = node.DataValue
textbox = dialog.Controls('FileDetails')
fso = CreateScriptService('FileSystem')
fso.FileNaming = 'SYS' # Only use the system file notation
if fso.FolderExists(fullpath):
textbox.Value = 'FOLDER: ' + fullpath
elif fso.FileExists(fullpath):
textbox.Value = 'FILE: ' + fullpath + \
'\n' + 'Length: ' + str(fso.GetFileLen(fullpath)) + ' bytes' + \
'\n' + 'Modified on: ' + str(fso.GetFileModified(fullpath))
# *******************************************************************
# * Fired when an item in the tree control is expanded
# *******************************************************************
def TreeExpanded(event = None):
# Triggered by the OnNodeExpanded event
# treecontrol A SFDialogs.DialogControl service instance
# node com.sun.star.awt.tree.XTreeNode
if event is None:
return
treecontrol = CreateScriptService('DialogEvent', event)
node = event.Node
if node.ChildCount > 0: # The node was expanded previously, do nothing
return
SetSubtree(treecontrol, node)
# *******************************************************************
# * Subfolders and subfiles
# * Called when root is created or when a folder is expanded
# *******************************************************************
def SetSubtree(treecontrol, node):
# Find all folders and files depending on the given node of the given treecontrol
# Sort them, folders first
# Add as subnodes all folders and files to the given node
# folder The folder represented by the fiven node
# subfiles List of files in the current folder
# subfolders List of subfolders in the current folder
# subitems List aggregating subfolders and subitems
# fso The ScriptForge.FileSystem service unique instance
# s Loop variable
fso = CreateScriptService('FileSystem')
fso.FileNaming = 'SYS' # Only use the system file notation
folder = node.DataValue
if fso.FolderExists(folder) is False: # The node is not a folder, exit
return
# Collect all subfolders and files contained below the node argument
subitems = fso.SubFolders(folder)
subfolders = sorted(subitems, key = str.casefold)
subitems = fso.Files(folder)
subfiles = sorted(subitems, key = str.casefold)
subitems = subfolders + subfiles
# Build the next level of the tree under the current node
for s in subitems:
treecontrol.AddSubNode(node, displayvalue = fso.GetName(s), datavalue = s)
# *******************************************************************
# * May be defined with the Basic IDE
# *******************************************************************
def SetupDialog():
# Build from scratch the example dialog and its controls
# dialog The returned SFDialogs.Dialog object
# control A SFDialogs.DialogControl object
dialog = CreateScriptService('NewDialog', 'Tree', (115, 65, 260, 217))
dialog.Caption = 'File picker'
# The close button
control = dialog.CreateButton('CloseButton', place = (230, 207, 30, 12), push = 'OK')
control.Caption = 'Close'
# The tree control
control = dialog.CreateTreeControl('FilePicker', place = (10, 6, 245, 160))
# The textbox with the details
control = dialog.CreateTextField('FileDetails', place = (10, 170, 245, 33), multiline = True)
return dialog
g_exportedScripts = (Main,)
if __name__ == '__main__':
Main()