summaryrefslogtreecommitdiff
path: root/wizards
diff options
context:
space:
mode:
authorJean-Pierre Ledure <jp@ledure.be>2020-12-03 11:33:08 +0100
committerJean-Pierre Ledure <jp@ledure.be>2020-12-03 17:42:41 +0100
commitd0fa04b4111d8b43d4249aeae96bb0f6fcd35e8e (patch)
tree1a02c1cb377c9958b28036f99691c42fb63a034d /wizards
parent60ae45f5846f69857c46b74d153fea1ef14d3c4d (diff)
ScriptForge: AddSubNode/AddSubTree for tree controls
A new dialog control is is introduced: the tree control The proposed methods let create a root node and build a tree, either branch by branch or many branches at once when they are issued from a sorted array Change-Id: I4265fd6e413be383a7b6df3b9cd754d657066c19 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107154 Tested-by: Jean-Pierre Ledure <jp@ledure.be> Tested-by: Jenkins Reviewed-by: Jean-Pierre Ledure <jp@ledure.be>
Diffstat (limited to 'wizards')
-rw-r--r--wizards/source/scriptforge/SF_Array.xba2
-rw-r--r--wizards/source/scriptforge/SF_Dictionary.xba2
-rw-r--r--wizards/source/scriptforge/SF_Exception.xba2
-rw-r--r--wizards/source/scriptforge/SF_L10N.xba2
-rw-r--r--wizards/source/scriptforge/SF_Root.xba2
-rw-r--r--wizards/source/scriptforge/SF_Services.xba2
-rw-r--r--wizards/source/scriptforge/SF_String.xba2
-rw-r--r--wizards/source/scriptforge/SF_Timer.xba2
-rw-r--r--wizards/source/scriptforge/SF_UI.xba2
-rw-r--r--wizards/source/scriptforge/SF_Utils.xba5
-rw-r--r--wizards/source/sfdialogs/SF_Dialog.xba9
-rw-r--r--wizards/source/sfdialogs/SF_DialogControl.xba259
12 files changed, 279 insertions, 12 deletions
diff --git a/wizards/source/scriptforge/SF_Array.xba b/wizards/source/scriptforge/SF_Array.xba
index e219a792e134..20c4632aa7ae 100644
--- a/wizards/source/scriptforge/SF_Array.xba
+++ b/wizards/source/scriptforge/SF_Array.xba
@@ -2546,4 +2546,4 @@ Dim iCompare As Integer, iVarType1 As Integer, iVarType2 As Integer
End Function &apos; ScriptForge.SF_Array._ValCompare
REM ================================================= END OF SCRIPTFORGE.SF_ARRAY
-</script:module>
+</script:module> \ No newline at end of file
diff --git a/wizards/source/scriptforge/SF_Dictionary.xba b/wizards/source/scriptforge/SF_Dictionary.xba
index 6cce27ea4a48..de10ed45fd4d 100644
--- a/wizards/source/scriptforge/SF_Dictionary.xba
+++ b/wizards/source/scriptforge/SF_Dictionary.xba
@@ -949,4 +949,4 @@ Const cstSeparator = &quot;, &quot;
End Function &apos; ScriptForge.SF_Dictionary._Repr
REM ============================================ END OF SCRIPTFORGE.SF_DICTIONARY
-</script:module>
+</script:module> \ No newline at end of file
diff --git a/wizards/source/scriptforge/SF_Exception.xba b/wizards/source/scriptforge/SF_Exception.xba
index 30da6907f4f5..a8e3067d57f5 100644
--- a/wizards/source/scriptforge/SF_Exception.xba
+++ b/wizards/source/scriptforge/SF_Exception.xba
@@ -1104,4 +1104,4 @@ Private Function _Repr() As String
End Function &apos; ScriptForge.SF_Exception._Repr
REM ============================================ END OF SCRIPTFORGE.SF_EXCEPTION
-</script:module>
+</script:module> \ No newline at end of file
diff --git a/wizards/source/scriptforge/SF_L10N.xba b/wizards/source/scriptforge/SF_L10N.xba
index fcb87ef1471b..8f526388d4c7 100644
--- a/wizards/source/scriptforge/SF_L10N.xba
+++ b/wizards/source/scriptforge/SF_L10N.xba
@@ -693,4 +693,4 @@ Private Function _Repr() As String
End Function &apos; ScriptForge.SF_L10N._Repr
REM ============================================ END OF SCRIPTFORGE.SF_L10N
-</script:module>
+</script:module> \ No newline at end of file
diff --git a/wizards/source/scriptforge/SF_Root.xba b/wizards/source/scriptforge/SF_Root.xba
index 2af6ca463dcb..339cc9db81bc 100644
--- a/wizards/source/scriptforge/SF_Root.xba
+++ b/wizards/source/scriptforge/SF_Root.xba
@@ -64,6 +64,7 @@ Private DatabaseContext As Object &apos; com.sun.star.sdb.DatabaseContext
Private ConfigurationProvider _
As Object &apos; com.sun.star.configuration.ConfigurationProvider
Private MailService As Object &apos; com.sun.star.system.SimpleCommandMail or com.sun.star.system.SimpleSystemMail
+Private TreeDataModel As Object &apos; com.sun.star.awt.tree.MutableTreeDataModel
&apos; Specific persistent services objects or properties
Private FileSystemNaming As String &apos; If &quot;SYS&quot;, file and folder naming is based on operating system notation
@@ -114,6 +115,7 @@ Private Sub Class_Initialize()
Set DatabaseContext = Nothing
Set ConfigurationProvider = Nothing
Set MailService = Nothing
+ Set TreeDataModel = Nothing
OSName = &quot;&quot;
SFDialogs = Empty
End Sub &apos; ScriptForge.SF_Root Constructor
diff --git a/wizards/source/scriptforge/SF_Services.xba b/wizards/source/scriptforge/SF_Services.xba
index be6482332d93..10b8c53978e2 100644
--- a/wizards/source/scriptforge/SF_Services.xba
+++ b/wizards/source/scriptforge/SF_Services.xba
@@ -604,4 +604,4 @@ Catch:
End Function &apos; ScriptForge.SF_Services._NewTimer
REM ============================================== END OF SCRIPTFORGE.SF_SERVICES
-</script:module>
+</script:module> \ No newline at end of file
diff --git a/wizards/source/scriptforge/SF_String.xba b/wizards/source/scriptforge/SF_String.xba
index 272a2d1cefa7..66eb90910ba5 100644
--- a/wizards/source/scriptforge/SF_String.xba
+++ b/wizards/source/scriptforge/SF_String.xba
@@ -2639,4 +2639,4 @@ Dim i As Long
End Function &apos; ScriptForge.SF_String._Repr
REM ================================================ END OF SCRIPTFORGE.SF_STRING
-</script:module>
+</script:module> \ No newline at end of file
diff --git a/wizards/source/scriptforge/SF_Timer.xba b/wizards/source/scriptforge/SF_Timer.xba
index f352e1135744..3bdcaa6b701e 100644
--- a/wizards/source/scriptforge/SF_Timer.xba
+++ b/wizards/source/scriptforge/SF_Timer.xba
@@ -460,4 +460,4 @@ Const cstMaxLength = 50 &apos; Maximum length for items
End Function &apos; ScriptForge.SF_Timer._Repr
REM ============================================ END OF SCRIPTFORGE.SF_TIMER
-</script:module>
+</script:module> \ No newline at end of file
diff --git a/wizards/source/scriptforge/SF_UI.xba b/wizards/source/scriptforge/SF_UI.xba
index ca6bf79e40ab..38bcb7645b4c 100644
--- a/wizards/source/scriptforge/SF_UI.xba
+++ b/wizards/source/scriptforge/SF_UI.xba
@@ -1172,4 +1172,4 @@ Private Function _Repr() As String
End Function &apos; ScriptForge.SF_UI._Repr
REM ============================================ END OF SCRIPTFORGE.SF_UI
-</script:module>
+</script:module> \ No newline at end of file
diff --git a/wizards/source/scriptforge/SF_Utils.xba b/wizards/source/scriptforge/SF_Utils.xba
index a3933be731d5..80c939b697bd 100644
--- a/wizards/source/scriptforge/SF_Utils.xba
+++ b/wizards/source/scriptforge/SF_Utils.xba
@@ -427,6 +427,11 @@ Dim vNodePath As Variant
Set .TextSearch = CreateUnoService(&quot;com.sun.star.util.TextSearch&quot;)
End If
Set _GetUNOService = .TextSearch
+ Case &quot;TreeDataModel&quot;
+ If IsEmpty(.TreeDataModel) Or IsNull(.TreeDataModel) Then
+ Set .TreeDataModel = CreateUnoService(&quot;com.sun.star.awt.tree.MutableTreeDataModel&quot;)
+ End If
+ Set _GetUNOService = .TreeDataModel
Case &quot;URLTransformer&quot;
If IsEmpty(.URLTransformer) Or IsNull(.URLTransformer) Then
Set .URLTransformer = CreateUnoService(&quot;com.sun.star.util.URLTransformer&quot;)
diff --git a/wizards/source/sfdialogs/SF_Dialog.xba b/wizards/source/sfdialogs/SF_Dialog.xba
index 5adfd515c33d..3d293e77e125 100644
--- a/wizards/source/sfdialogs/SF_Dialog.xba
+++ b/wizards/source/sfdialogs/SF_Dialog.xba
@@ -70,6 +70,14 @@ Private _DialogModel As Object &apos; com.sun.star.awt.XControlModel - stardiv
Private _Displayed As Boolean &apos; True after Execute()
Private _Modal As Boolean &apos; Set by Execute()
+&apos; Cache for TreeControl events
+Private _TreeCache As Object &apos; Dictionary: key = control name, item = _TreeControl
+
+Type _TreeControl
+ OnNodeSelected As String
+ OnNodeExpanded As String
+End Type
+
REM ============================================================ MODULE CONSTANTS
Private Const OKBUTTON = 1
@@ -92,6 +100,7 @@ Private Sub Class_Initialize()
Set _DialogModel = Nothing
_Displayed = False
_Modal = True
+ Set _TreeCache = ScriptForge.SF_Services.CreateScriptService(&quot;Dictionary&quot;)
End Sub &apos; SFDialogs.SF_Dialog Constructor
REM -----------------------------------------------------------------------------
diff --git a/wizards/source/sfdialogs/SF_DialogControl.xba b/wizards/source/sfdialogs/SF_DialogControl.xba
index 7200f1b25876..56d362e48a52 100644
--- a/wizards/source/sfdialogs/SF_DialogControl.xba
+++ b/wizards/source/sfdialogs/SF_DialogControl.xba
@@ -23,6 +23,12 @@ Option Explicit
&apos;&apos;&apos; Essentially a single property &quot;Value&quot; maps many alternative UNO properties depending each on
&apos;&apos;&apos; the control type.
&apos;&apos;&apos;
+&apos;&apos;&apos; A special attention is given to controls with type TreeControl.
+&apos;&apos;&apos; It is easy with the API proposed in the current class to populate a tree, either
+&apos;&apos;&apos; - branch by branch (CreateRoot and AddChild), or
+&apos;&apos;&apos; - with a set of branches at once (AddSubtree)
+&apos;&apos;&apos; Additionally populating a TreeConctrol can be done statically or dynamically
+&apos;&apos;&apos;
&apos;&apos;&apos; Service invocation:
&apos;&apos;&apos; Dim myDialog As Object, myControl As Object
&apos;&apos;&apos; Set myDialog = CreateScriptService(&quot;SFDialogs.Dialog&quot;, &quot;GlobalScope&quot;, myLibrary, DialogName)
@@ -53,6 +59,7 @@ Private _DialogName As String &apos; Parent dialog name
&apos; Control UNO references
Private _ControlModel As Object &apos; com.sun.star.awt.XControlModel
Private _ControlView As Object &apos; com.sun.star.awt.XControl - stardiv.Toolkit.UnoDialogControl
+Private _TreeDataModel As Object &apos; com.sun.star.awt.tree.MutableTreeDataModel
&apos; Control attributes
Private _ImplementationName As String
@@ -79,6 +86,7 @@ Private Const CTLRADIOBUTTON = &quot;RadioButton&quot;
Private Const CTLSCROLLBAR = &quot;ScrollBar&quot;
Private Const CTLTEXTFIELD = &quot;TextField&quot;
Private Const CTLTIMEFIELD = &quot;TimeField&quot;
+Private Const CTLTREECONTROL = &quot;TreeControl&quot;
REM ===================================================== CONSTRUCTOR/DESTRUCTOR
@@ -92,6 +100,7 @@ Private Sub Class_Initialize()
_DialogName = &quot;&quot;
Set _ControlModel = Nothing
Set _ControlView = Nothing
+ Set _TreeDataModel = Nothing
_ImplementationName = &quot;&quot;
_ControlType = &quot;&quot;
End Sub &apos; SFDialogs.SF_DialogControl Constructor
@@ -382,6 +391,30 @@ Property Let OnMouseReleased(Optional ByVal pvOnMouseReleased As Variant)
End Property &apos; SFDialogs.SF_DialogControl.OnMouseReleased (let)
REM -----------------------------------------------------------------------------
+Property Get OnNodeExpanded() As Variant
+&apos;&apos;&apos; Get the script associated with the OnNodeExpanded event
+ OnNodeExpanded = _PropertyGet(&quot;OnNodeExpanded&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnNodeExpanded (get)
+
+REM -----------------------------------------------------------------------------
+Property Let OnNodeExpanded(Optional ByVal pvOnNodeExpanded As Variant)
+&apos;&apos;&apos; Set the updatable property OnNodeExpanded
+ _PropertySet(&quot;OnNodeExpanded&quot;, pvOnNodeExpanded)
+End Property &apos; SFDialogs.SF_DialogControl.OnNodeExpanded (let)
+
+REM -----------------------------------------------------------------------------
+Property Get OnNodeSelected() As Variant
+&apos;&apos;&apos; Get the script associated with the OnNodeSelected event
+ OnNodeSelected = _PropertyGet(&quot;OnNodeSelected&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnNodeSelected (get)
+
+REM -----------------------------------------------------------------------------
+Property Let OnNodeSelected(Optional ByVal pvOnNodeSelected As Variant)
+&apos;&apos;&apos; Set the updatable property OnNodeSelected
+ _PropertySet(&quot;OnNodeSelected&quot;, pvOnNodeSelected)
+End Property &apos; SFDialogs.SF_DialogControl.OnNodeSelected (let)
+
+REM -----------------------------------------------------------------------------
Property Get OnTextChanged() As Variant
&apos;&apos;&apos; Get the script associated with the OnTextChanged event
OnTextChanged = _PropertyGet(&quot;OnTextChanged&quot;)
@@ -507,9 +540,221 @@ Property Get XControlView() As Object
XControlView = _PropertyGet(&quot;XControlView&quot;, Nothing)
End Property &apos; SFDialogs.SF_DialogControl.XControlView (get)
+REM -----------------------------------------------------------------------------
+Property Get XTreeDataModel() As Object
+&apos;&apos;&apos; The XTreeDataModel property returns the model UNO object of the control
+ XTreeDataModel = _PropertyGet(&quot;XTreeDataModel&quot;, Nothing)
+End Property &apos; SFDialogs.SF_DialogControl.XTreeDataModel (get)
+
REM ===================================================================== METHODS
REM -----------------------------------------------------------------------------
+Public Function AddSubNode(Optional ByRef ParentNode As Variant _
+ , Optional ByVal DisplayValue As Variant _
+ , Optional ByRef DataValue As Variant _
+ ) As Variant
+&apos;&apos;&apos; Return a new node of the tree control subordinate to a parent node
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; ParentNode: A node UNO object, of type com.sun.star.awt.tree.XMutableTreeNode
+&apos;&apos;&apos; DisplayValue: the text appearing in the control box
+&apos;&apos;&apos; DataValue: any value associated with the new node. Default = Empty
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The new node UNO object: com.sun.star.awt.tree.XMutableTreeNode
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; Dim myTree As Object, myNode As Object, theRoot As Object
+&apos;&apos;&apos; Set myTree = myDialog.Controls(&quot;myTreeControl&quot;)
+&apos;&apos;&apos; Set theRoot = myTree.CreateRoot(&quot;Tree top&quot;)
+&apos;&apos;&apos; Set myNode = myTree.AddSubNode(theRoot, &quot;A branch ...&quot;)
+
+Dim oNode As Object &apos; Return value
+Const cstThisSub = &quot;SFDialogs.DialogControl.AddSubNode&quot;
+Const cstSubArgs = &quot;ParentNode, DisplayValue, [DataValue=Empty]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ Set oNode = Nothing
+
+Check:
+ If IsMissing(DataValue) Then DataValue = Empty
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(ParentNode, &quot;ParentNode&quot;, V_OBJECT) Then GoTo Catch
+ If ScriptForge.SF_Session.UnoObjectType(ParentNode) &lt;&gt; &quot;toolkit.MutableTreeNode&quot; Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(DisplayValue, &quot;DisplayValue&quot;, V_STRING) Then GoTo Catch
+ End If
+
+Try:
+ With _TreeDataModel
+ Set oNode = .createNode(DisplayValue, True)
+ oNode.DataValue = DataValue
+ ParentNode.appendChild(oNode)
+ End With
+
+Finally:
+ Set AddSubNode = oNode
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_DialogControl.AddSubNode
+
+REM -----------------------------------------------------------------------------
+Public Function AddSubTree(Optional ByRef ParentNode As Variant _
+ , Optional ByRef FlatTree As Variant _
+ , Optional ByVal WithDataValue As Variant _
+ ) As Boolean
+&apos;&apos;&apos; Return True when a subtree, subordinate to a parent node, could be inserted successfully in a tree control
+&apos;&apos;&apos; If the parent node had already child nodes before calling this method, the child nodes are erased
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; ParentNode: A node UNO object, of type com.sun.star.awt.tree.XMutableTreeNode
+&apos;&apos;&apos; FlatTree: a 2D array sorted on the columns containing the DisplayValues
+&apos;&apos;&apos; Flat tree &gt;&gt;&gt;&gt; Resulting subtree
+&apos;&apos;&apos; A1 B1 C1 |__ A1
+&apos;&apos;&apos; A1 B1 C2 |__ B1
+&apos;&apos;&apos; A1 B2 C3 |__ C1
+&apos;&apos;&apos; A2 B3 C4 |__ C2
+&apos;&apos;&apos; A2 B3 C5 B2
+&apos;&apos;&apos; A3 B4 C6 |__ C3
+&apos;&apos;&apos; |__ A2
+&apos;&apos;&apos; |__ B3
+&apos;&apos;&apos; |__ C4
+&apos;&apos;&apos; |__ C5
+&apos;&apos;&apos; |__ A3
+&apos;&apos;&apos; |__ B4
+&apos;&apos;&apos; |__ C6
+&apos;&apos;&apos; Typically, such an array can be issued by the GetRows method applied on the SFDatabases.Database service
+&apos;&apos;&apos; when the array item containing the text to be displayed is = &quot;&quot; or is empty/null,
+&apos;&apos;&apos; no new subnode is created and the remainder of the row is skipped
+&apos;&apos;&apos; WithDataValue:
+&apos;&apos;&apos; When False (default), every column of FlatTree contains the text to be displayed in the tree control
+&apos;&apos;&apos; When True, the texts to be displayed (DisplayValue) are in columns 0, 2, 4, ...
+&apos;&apos;&apos; while the DataValues are in columns 1, 3, 5, ...
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The new node UNO object: com.sun.star.awt.tree.XMutableTreeNode
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; Dim myTree As Object, theRoot As Object, oDb As Object, vData As Variant
+&apos;&apos;&apos; Set myTree = myDialog.Controls(&quot;myTreeControl&quot;)
+&apos;&apos;&apos; Set theRoot = myTree.CreateRoot(&quot;By product category&quot;)
+&apos;&apos;&apos; Set oDb = CreateScriptService(&quot;SFDatabases.Database&quot;, &quot;/home/.../mydatabase.odb&quot;)
+&apos;&apos;&apos; vData = oDb.GetRows(&quot;SELECT [Category].[Name], [Category].[ID], [Product].[Name], [Product].[ID] &quot; _
+&apos;&apos;&apos; &amp; &quot;FROM [Category], [PRODUCT] WHERE [Product].[CategoryID] = [Category].[ID] &quot; _
+&apos;&apos;&apos; &amp; &quot;ORDER BY [Category].[Name], [Product].[Name]&quot;)
+&apos;&apos;&apos; myTree.AddSubTree(theRoot, vData)
+
+Dim bSubTree As Boolean &apos; Return value
+Dim oNode As Object &apos; com.sun.star.awt.tree.XMutableTreeNode
+Dim oNewNode As Object &apos; com.sun.star.awt.tree.XMutableTreeNode
+Dim lChildCount As Long &apos; Number of children nodes of a parent node
+Dim iStep As Integer &apos; 1 when WithDataValue = False, 2 otherwise
+Dim bChange As Boolean &apos; When True, the item in FlatTree is different from the item above
+Dim sValue As String &apos; Alias for display values
+Dim i As Long, j As Long
+Const cstThisSub = &quot;SFDialogs.DialogControl.AddSubTree&quot;
+Const cstSubArgs = &quot;ParentNode, FlatTree, [WithDataValue=False]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bSubTree = False
+
+Check:
+ If IsMissing(WithDataValue) Or IsEmpty(WithDataValue) Then WithDataValue = False
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(ParentNode, &quot;ParentNode&quot;, V_OBJECT) Then GoTo Catch
+ If ScriptForge.SF_Session.UnoObjectType(ParentNode) &lt;&gt; &quot;toolkit.MutableTreeNode&quot; Then GoTo Catch
+ If Not ScriptForge.SF_Utils._ValidateArray(FlatTree, &quot;FlatTree&quot;, 2) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(WithDataValue, &quot;WithDataValue&quot;, V_BOOLEAN) Then GoTo Catch
+ End If
+
+Try:
+ With _TreeDataModel
+ &apos; Clean subtree
+ lChildCount = ParentNode.getChildCount()
+ For i = 1 To lChildCount
+ ParentNode.removeChildByIndex(0) &apos; This cleans all subtrees too
+ Next i
+ &apos; Build a new subtree
+ If UBound(FlatTree, 1) &lt; LBound(FlatTree, 1) Then &apos;Array is empty
+ Else
+ iStep = Iif(WithDataValue, 2, 1)
+ For i = LBound(FlatTree, 1) To UBound(FlatTree, 1) &apos; Array rows
+ bChange = ( i = 0 )
+ &apos; Restart from the parent node at each i-iteration
+ Set oNode = ParentNode
+ For j = LBound(FlatTree, 2) To UBound(FlatTree, 2) Step iStep &apos; Array columns
+ If FlatTree(i, j) = &quot;&quot; Or IsNull(FlatTree(i, j)) Or IsEmpty(FlatTree(i, j)) Then
+ Set oNode = Nothing
+ Exit For &apos; Exit j-loop
+ End If
+ If Not bChange Then bChange = ( FlatTree(i, j) &lt;&gt; FlatTree(i - 1, j) )
+ If bChange Then &apos; Create new subnode at tree depth = j
+ If VarType(FlatTree(i, j)) = V_STRING Then sValue = FlatTree(i, j) Else sValue = ScriptForge.SF_String.Represent(FlatTree(i, j))
+ Set oNewNode = .createNode(sValue, True)
+ If WithDataValue Then oNewNode.DataValue = FlatTree(i, j + 1)
+ oNode.appendChild(oNewNode)
+ Set oNode = oNewNode
+ Else
+ &apos; Position next current node on last child of actual current node
+ lChildCount = oNode.getChildCount()
+ If lChildCount &gt; 0 Then Set oNode = oNode.getChildAt(lChildCount - 1) Else Set oNode = Nothing
+ End If
+ Next j
+ Next i
+ End If
+ End With
+
+Finally:
+ AddSubTree = bSubTree
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_DialogControl.AddSubTree
+
+REM -----------------------------------------------------------------------------
+Public Function CreateRoot(Optional ByVal DisplayValue As Variant _
+ , Optional ByRef DataValue As Variant _
+ ) As Variant
+&apos;&apos;&apos; Return a new root node of the tree control. The new tree root is inserted below pre-exiting root nodes
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; DisplayValue: the text appearing in the control box
+&apos;&apos;&apos; DataValue: any value associated with the root node. Default = Empty
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The new root node as a UNO object of type com.sun.star.awt.tree.XMutableTreeNode
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; Dim myTree As Object, myNode As Object
+&apos;&apos;&apos; Set myTree = myDialog.Controls(&quot;myTreeControl&quot;)
+&apos;&apos;&apos; Set myNode = myTree.CreateRoot(&quot;Tree starts here ...&quot;)
+
+Dim oRoot As Object &apos; Return value
+Const cstThisSub = &quot;SFDialogs.DialogControl.CreateRoot&quot;
+Const cstSubArgs = &quot;DisplayValue, [DataValue=Empty]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ Set oRoot = Nothing
+
+Check:
+ If IsMissing(DataValue) Then DataValue = Empty
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(DisplayValue, &quot;DisplayValue&quot;, V_STRING) Then GoTo Catch
+ End If
+
+Try:
+ With _TreeDataModel
+ Set oRoot = .createNode(DisplayValue, True)
+ oRoot.DataValue = DataValue
+ .setRoot(oRoot)
+ &apos; To be visible, a root must have contained at least 1 child. Create a fictive one and erase it.
+ &apos; This behavious does not seem related to the RootDisplayed property ??
+ oRoot.appendChild(.createNode(&quot;Something&quot;, False))
+ oRoot.removeChildByIndex(0)
+ End With
+
+Finally:
+ Set CreateRoot = oRoot
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_DialogControl.CreateRoot
+
+REM -----------------------------------------------------------------------------
Public Function GetProperty(Optional ByVal PropertyName As Variant) As Variant
&apos;&apos;&apos; Return the actual value of the given property
&apos;&apos;&apos; Args:
@@ -833,10 +1078,14 @@ Try:
vServiceName = Split(_ControlModel.getServiceName(), &quot;.&quot;)
sType = vServiceName(UBound(vServiceName))
Select Case sType
- Case &quot;UnoControlSpinButtonModel&quot;, &quot;TreeControlModel&quot;
- _ControlType = &quot;&quot; &apos; Not supported
- Case &quot;Edit&quot; : _ControlType = CTLTEXTFIELD
- Case Else : _ControlType = sType
+ Case &quot;UnoControlSpinButtonModel&quot;
+ _ControlType = &quot;&quot; &apos; Not supported
+ Case &quot;Edit&quot; : _ControlType = CTLTEXTFIELD
+ Case &quot;TreeControlModel&quot; &apos; Initialize the data model
+ _ControlType = CTLTREECONTROL
+ Set _ControlModel.DataModel = ScriptForge.SF_Utils._GetUNOService(&quot;TreeDataModel&quot;)
+ _TreeDataModel = _ControlModel.DataModel
+ Case Else : _ControlType = sType
End Select
Finally:
@@ -1067,6 +1316,8 @@ Const cstSubArgs = &quot;&quot;
Set _PropertyGet = _ControlModel
Case UCase(&quot;XControlView&quot;)
Set _PropertyGet = _ControlView
+ Case UCase(&quot;XTreeDataModel&quot;)
+ Set _PropertyGet = _TreeDataModel
Case Else
_PropertyGet = Null
End Select