summaryrefslogtreecommitdiffstats
path: root/wizards/source/sfdialogs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--wizards/source/sfdialogs/SF_Dialog.xba1111
-rw-r--r--wizards/source/sfdialogs/SF_DialogControl.xba2084
-rw-r--r--wizards/source/sfdialogs/SF_DialogListener.xba113
-rw-r--r--wizards/source/sfdialogs/SF_Register.xba348
-rw-r--r--wizards/source/sfdialogs/__License.xba26
-rw-r--r--wizards/source/sfdialogs/dialog.xlb3
-rw-r--r--wizards/source/sfdialogs/script.xlb9
7 files changed, 3694 insertions, 0 deletions
diff --git a/wizards/source/sfdialogs/SF_Dialog.xba b/wizards/source/sfdialogs/SF_Dialog.xba
new file mode 100644
index 000000000..da2afcb4a
--- /dev/null
+++ b/wizards/source/sfdialogs/SF_Dialog.xba
@@ -0,0 +1,1111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
+<script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_Dialog" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
+REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
+REM === The SFDialogs library is one of the associated libraries. ===
+REM === Full documentation is available on https://help.libreoffice.org/ ===
+REM =======================================================================================================================
+
+Option Compatible
+Option ClassModule
+
+Option Explicit
+
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+&apos;&apos;&apos; SF_Dialog
+&apos;&apos;&apos; =========
+&apos;&apos;&apos; Management of dialogs defined with the Basic IDE
+&apos;&apos;&apos; Each instance of the current class represents a single dialog box displayed to the user
+&apos;&apos;&apos;
+&apos;&apos;&apos; A dialog box can be displayed in modal or in non-modal modes
+&apos;&apos;&apos; In modal mode, the box is displayed and the execution of the macro process is suspended
+&apos;&apos;&apos; until one of the OK or Cancel buttons is pressed. In the meantime, other user actions
+&apos;&apos;&apos; executed on the box can trigger specific actions.
+&apos;&apos;&apos; In non-modal mode, the dialog box is &quot;floating&quot; on the user desktop and the execution
+&apos;&apos;&apos; of the macro process continues normally
+&apos;&apos;&apos; A dialog box disappears from memory after its explicit termination.
+&apos;&apos;&apos;
+&apos;&apos;&apos; Service invocation and usage:
+&apos;&apos;&apos; Dim myDialog As Object, lButton As Long
+&apos;&apos;&apos; Set myDialog = CreateScriptService(&quot;SFDialogs.Dialog&quot;, Container, Library, DialogName)
+&apos;&apos;&apos; &apos; Args:
+&apos;&apos;&apos; &apos; Container: &quot;GlobalScope&quot; for preinstalled libraries
+&apos;&apos;&apos; &apos; A window name (see its definition in the ScriptForge.UI service)
+&apos;&apos;&apos; &apos; &quot;&quot; (default) = the current document
+&apos;&apos;&apos; &apos; Library: The (case-sensitive) name of a library contained in the container
+&apos;&apos;&apos; &apos; Default = &quot;Standard&quot;
+&apos;&apos;&apos; &apos; DialogName: a case-sensitive string designating the dialog where it is about
+&apos;&apos;&apos; &apos; ... Initialize controls ...
+&apos;&apos;&apos; lButton = myDialog.Execute() &apos; Default mode = Modal
+&apos;&apos;&apos; If lButton = myDialog.OKBUTTON Then
+&apos;&apos;&apos; &apos; ... Process controls and do what is needed
+&apos;&apos;&apos; End If
+&apos;&apos;&apos; myDialog.Terminate()
+&apos;&apos;&apos;
+&apos;&apos;&apos; Detailed user documentation:
+&apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_dialog.html?DbPAR=BASIC
+&apos;&apos;&apos;
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+
+REM ================================================================== EXCEPTIONS
+
+Private Const DIALOGDEADERROR = &quot;DIALOGDEADERROR&quot;
+
+REM ============================================================= PRIVATE MEMBERS
+
+Private [Me] As Object
+Private [_Parent] As Object
+Private ObjectType As String &apos; Must be DIALOG
+Private ServiceName As String
+
+&apos; Dialog location
+Private _Container As String
+Private _Library As String
+Private _Name As String
+Private _CacheIndex As Long &apos; Index in cache storage
+
+&apos; Dialog UNO references
+Private _DialogProvider As Object &apos; com.sun.star.io.XInputStreamProvider
+Private _DialogControl As Object &apos; com.sun.star.awt.XControl - stardiv.Toolkit.UnoDialogControl
+Private _DialogModel As Object &apos; com.sun.star.awt.XControlModel - stardiv.Toolkit.UnoControlDialogModel
+
+&apos; Dialog attributes
+Private _Displayed As Boolean &apos; True after Execute()
+Private _Modal As Boolean &apos; Set by Execute()
+
+&apos; Dialog position and dimensions
+Private _Left As Long
+Private _Top As Long
+Private _Width As Long
+Private _Height As Long
+
+&apos; Persistent storage for controls
+Private _ControlCache As Variant &apos; Array of control objects sorted like ElementNames of the Dialog model
+
+REM ============================================================ MODULE CONSTANTS
+
+Private Const OKBUTTON = 1
+Private Const CANCELBUTTON = 0
+
+REM ====================================================== CONSTRUCTOR/DESTRUCTOR
+
+REM -----------------------------------------------------------------------------
+Private Sub Class_Initialize()
+ Set [Me] = Nothing
+ Set [_Parent] = Nothing
+ ObjectType = &quot;DIALOG&quot;
+ ServiceName = &quot;SFDialogs.Dialog&quot;
+ _Container = &quot;&quot;
+ _Library = &quot;&quot;
+ _Name = &quot;&quot;
+ _CacheIndex = -1
+ Set _DialogProvider = Nothing
+ Set _DialogControl = Nothing
+ Set _DialogModel = Nothing
+ _Displayed = False
+ _Modal = True
+ _Left = -1
+ _Top = -1
+ _Width = -1
+ _Height = -1
+ _ControlCache = Array()
+End Sub &apos; SFDialogs.SF_Dialog Constructor
+
+REM -----------------------------------------------------------------------------
+Private Sub Class_Terminate()
+ Call Class_Initialize()
+End Sub &apos; SFDialogs.SF_Dialog Destructor
+
+REM -----------------------------------------------------------------------------
+Public Function Dispose() As Variant
+ If _CacheIndex &gt;= 0 Then Terminate()
+ Call Class_Terminate()
+ Set Dispose = Nothing
+End Function &apos; SFDialogs.SF_Dialog Explicit Destructor
+
+REM ================================================================== PROPERTIES
+
+REM -----------------------------------------------------------------------------
+Property Get Caption() As Variant
+&apos;&apos;&apos; The Caption property refers to the title of the dialog
+ Caption = _PropertyGet(&quot;Caption&quot;)
+End Property &apos; SFDialogs.SF_Dialog.Caption (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Caption(Optional ByVal pvCaption As Variant)
+&apos;&apos;&apos; Set the updatable property Caption
+ _PropertySet(&quot;Caption&quot;, pvCaption)
+End Property &apos; SFDialogs.SF_Dialog.Caption (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Height() As Variant
+&apos;&apos;&apos; The Height property refers to the height of the dialog box
+ Height = _PropertyGet(&quot;Height&quot;)
+End Property &apos; SFDialogs.SF_Dialog.Height (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Height(Optional ByVal pvHeight As Variant)
+&apos;&apos;&apos; Set the updatable property Height
+ _PropertySet(&quot;Height&quot;, pvHeight)
+End Property &apos; SFDialogs.SF_Dialog.Height (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Modal() As Boolean
+&apos;&apos;&apos; The Modal property specifies if the dialog box has been executed in modal mode
+ Modal = _PropertyGet(&quot;Modal&quot;)
+End Property &apos; SFDialogs.SF_Dialog.Modal (get)
+
+REM -----------------------------------------------------------------------------
+Property Get Name() As String
+&apos;&apos;&apos; Return the name of the actual dialog
+ Name = _PropertyGet(&quot;Name&quot;)
+End Property &apos; SFDialogs.SF_Dialog.Name
+
+REM -----------------------------------------------------------------------------
+Property Get OnFocusGained() As Variant
+&apos;&apos;&apos; Get the script associated with the OnFocusGained event
+ OnFocusGained = _PropertyGet(&quot;OnFocusGained&quot;)
+End Property &apos; SFDialogs.SF_Dialog.OnFocusGained (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnFocusLost() As Variant
+&apos;&apos;&apos; Get the script associated with the OnFocusLost event
+ OnFocusLost = _PropertyGet(&quot;OnFocusLost&quot;)
+End Property &apos; SFDialogs.SF_Dialog.OnFocusLost (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnKeyPressed() As Variant
+&apos;&apos;&apos; Get the script associated with the OnKeyPressed event
+ OnKeyPressed = _PropertyGet(&quot;OnKeyPressed&quot;)
+End Property &apos; SFDialogs.SF_Dialog.OnKeyPressed (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnKeyReleased() As Variant
+&apos;&apos;&apos; Get the script associated with the OnKeyReleased event
+ OnKeyReleased = _PropertyGet(&quot;OnKeyReleased&quot;)
+End Property &apos; SFDialogs.SF_Dialog.OnKeyReleased (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnMouseDragged() As Variant
+&apos;&apos;&apos; Get the script associated with the OnMouseDragged event
+ OnMouseDragged = _PropertyGet(&quot;OnMouseDragged&quot;)
+End Property &apos; SFDialogs.SF_Dialog.OnMouseDragged (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnMouseEntered() As Variant
+&apos;&apos;&apos; Get the script associated with the OnMouseEntered event
+ OnMouseEntered = _PropertyGet(&quot;OnMouseEntered&quot;)
+End Property &apos; SFDialogs.SF_Dialog.OnMouseEntered (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnMouseExited() As Variant
+&apos;&apos;&apos; Get the script associated with the OnMouseExited event
+ OnMouseExited = _PropertyGet(&quot;OnMouseExited&quot;)
+End Property &apos; SFDialogs.SF_Dialog.OnMouseExited (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnMouseMoved() As Variant
+&apos;&apos;&apos; Get the script associated with the OnMouseMoved event
+ OnMouseMoved = _PropertyGet(&quot;OnMouseMoved&quot;)
+End Property &apos; SFDialogs.SF_Dialog.OnMouseMoved (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnMousePressed() As Variant
+&apos;&apos;&apos; Get the script associated with the OnMousePressed event
+ OnMousePressed = _PropertyGet(&quot;OnMousePressed&quot;)
+End Property &apos; SFDialogs.SF_Dialog.OnMousePressed (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnMouseReleased() As Variant
+&apos;&apos;&apos; Get the script associated with the OnMouseReleased event
+ OnMouseReleased = _PropertyGet(&quot;OnMouseReleased&quot;)
+End Property &apos; SFDialogs.SF_Dialog.OnMouseReleased (get)
+
+REM -----------------------------------------------------------------------------
+Property Get Page() As Variant
+&apos;&apos;&apos; A dialog may have several pages that can be traversed by the user step by step. The Page property of the Dialog object defines which page of the dialog is active.
+&apos;&apos;&apos; The Page property of a control defines the page of the dialog on which the control is visible.
+&apos;&apos;&apos; For example, if a control has a page value of 1, it is only visible on page 1 of the dialog.
+&apos;&apos;&apos; If the page value of the dialog is increased from 1 to 2, then all controls with a page value of 1 disappear and all controls with a page value of 2 become visible.
+ Page = _PropertyGet(&quot;Page&quot;)
+End Property &apos; SFDialogs.SF_Dialog.Page (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Page(Optional ByVal pvPage As Variant)
+&apos;&apos;&apos; Set the updatable property Page
+ _PropertySet(&quot;Page&quot;, pvPage)
+End Property &apos; SFDialogs.SF_Dialog.Page (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Visible() As Variant
+&apos;&apos;&apos; The Visible property is False before the Execute() statement
+ Visible = _PropertyGet(&quot;Visible&quot;)
+End Property &apos; SFDialogs.SF_Dialog.Visible (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Visible(Optional ByVal pvVisible As Variant)
+&apos;&apos;&apos; Set the updatable property Visible
+ _PropertySet(&quot;Visible&quot;, pvVisible)
+End Property &apos; SFDialogs.SF_Dialog.Visible (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Width() As Variant
+&apos;&apos;&apos; The Width property refers to the Width of the dialog box
+ Width = _PropertyGet(&quot;Width&quot;)
+End Property &apos; SFDialogs.SF_Dialog.Width (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Width(Optional ByVal pvWidth As Variant)
+&apos;&apos;&apos; Set the updatable property Width
+ _PropertySet(&quot;Width&quot;, pvWidth)
+End Property &apos; SFDialogs.SF_Dialog.Width (let)
+
+REM -----------------------------------------------------------------------------
+Property Get XDialogModel() As Object
+&apos;&apos;&apos; The XDialogModel property returns the model UNO object of the dialog
+ XDialogModel = _PropertyGet(&quot;XDialogModel&quot;)
+End Property &apos; SFDialogs.SF_Dialog.XDialogModel (get)
+
+REM -----------------------------------------------------------------------------
+Property Get XDialogView() As Object
+&apos;&apos;&apos; The XDialogView property returns the view UNO object of the dialog
+ XDialogView = _PropertyGet(&quot;XDialogView&quot;)
+End Property &apos; SFDialogs.SF_Dialog.XDialogView (get)
+
+REM ===================================================================== METHODS
+
+REM -----------------------------------------------------------------------------
+Public Function Activate() As Boolean
+&apos;&apos;&apos; Set the focus on the current dialog instance
+&apos;&apos;&apos; Probably called from after an event occurrence or to focus on a non-modal dialog
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; True if focusing is successful
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Dim oDlg As Object
+&apos;&apos;&apos; Set oDlg = CreateScriptService(,, &quot;myDialog&quot;) &apos; Dialog stored in current document&apos;s standard library
+&apos;&apos;&apos; oDlg.Activate()
+
+Dim bActivate As Boolean &apos; Return value
+Const cstThisSub = &quot;SFDialogs.Dialog.Activate&quot;
+Const cstSubArgs = &quot;&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bActivate = False
+
+Check:
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not _IsStillAlive() Then GoTo Finally
+ End If
+Try:
+ If Not IsNull(_DialogControl) Then
+ _DialogControl.setFocus()
+ bActivate = True
+ End If
+
+Finally:
+ Activate = bActivate
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_Dialog.Activate
+
+REM -----------------------------------------------------------------------------
+Public Function Center(Optional ByRef Parent As Variant) As Boolean
+&apos;&apos;&apos; Center the actual dialog instance in the middle of a parent window
+&apos;&apos;&apos; Without arguments, the method centers the dialog in the middle of the current window
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Parent: an object, either
+&apos;&apos;&apos; - a ScriptForge dialog object
+&apos;&apos;&apos; - a ScriptForge document (Calc, Base, ...) object
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; True when successful
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; Sub TriggerEvent(oEvent As Object)
+&apos;&apos;&apos; Dim oDialog1 As Object, oDialog2 As Object, lExec As Long
+&apos;&apos;&apos; Set oDialog1 = CreateScriptService(&quot;DialogEvent&quot;, oEvent) &apos; The dialog having caused the event
+&apos;&apos;&apos; Set oDialog2 = CreateScriptService(&quot;Dialog&quot;, ...) &apos; Open a second dialog
+&apos;&apos;&apos; oDialog2.Center(oDialog1)
+&apos;&apos;&apos; lExec = oDialog2.Execute()
+&apos;&apos;&apos; Select Case lExec
+&apos;&apos;&apos; ...
+&apos;&apos;&apos; End Sub
+
+Dim bCenter As Boolean &apos; Return value
+Dim oUi As Object &apos; ScriptForge.SF_UI
+Dim oObjDesc As Object &apos; _ObjectDescriptor type
+Dim sObjectType As String &apos; Can be uno or sf object type
+Dim oParent As Object &apos; UNO alias of parent
+Dim oParentPosSize As Object &apos; Parent com.sun.star.awt.Rectangle
+Dim lParentX As Long &apos; X position of parent dialog
+Dim lParentY As Long &apos; Y position of parent dialog
+Dim oPosSize As Object &apos; Dialog com.sun.star.awt.Rectangle
+Const cstThisSub = &quot;SFDialogs.Dialog.Center&quot;
+Const cstSubArgs = &quot;[Parent]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bCenter = False
+
+Check:
+ If IsMissing(Parent) Or IsEmpty(Parent) Then Set Parent = Nothing
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(Parent, &quot;Parent&quot;, ScriptForge.V_OBJECT) Then GoTo Finally
+ End If
+
+ Set oParentPosSize = Nothing
+ lParentX = 0 : lParentY = 0
+ If IsNull(Parent) Then
+ Set oUi = CreateScriptService(&quot;UI&quot;)
+ Set oParentPosSize = oUi._PosSize() &apos; Return the position and dimensions of the active window
+ Else
+ &apos; Determine the object type
+ Set oObjDesc = ScriptForge.SF_Utils._VarTypeObj(Parent)
+ If oObjDesc.iVarType = ScriptForge.V_SFOBJECT Then &apos; ScriptForge object
+ sObjectType = oObjDesc.sObjectType
+ &apos; Document or dialog ?
+ If Not ScriptForge.SF_Array.Contains(Array(&quot;BASE&quot;, &quot;CALC&quot;, &quot;DIALOG&quot;, &quot;DOCUMENT&quot;, &quot;WRITER&quot;), sObjectType, CaseSensitive := True) Then GoTo Finally
+ If sObjectType = &quot;DIALOG&quot; Then
+ Set oParent = Parent._DialogControl
+ Set oParentPosSize = oParent.getPosSize()
+ lParentX = oParentPosSize.X
+ lParentY = oParentPosSize.Y
+ Else
+ Set oParent = Parent._Component.getCurrentController().Frame.getComponentWindow()
+ Set oParentPosSize = oParent.getPosSize()
+ End If
+ Else
+ GoTo Finally &apos; UNO object, do nothing
+ End If
+ End If
+ If IsNull(oParentPosSize) Then GoTo Finally
+
+Try:
+ Set oPosSize = _DialogControl.getPosSize()
+ With oPosSize
+ _DialogControl.setPosSize( _
+ lParentX + CLng((oParentPosSize.Width - .Width) \ 2) _
+ , lParentY + CLng((oParentPosSize.Height - .Height) \ 2) _
+ , .Width _
+ , .Height _
+ , com.sun.star.awt.PosSize.POSSIZE)
+ End With
+ bCenter = True
+
+Finally:
+ Center = bCenter
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SF_Documents.SF_Dialog.Center
+
+REM -----------------------------------------------------------------------------
+Public Function Controls(Optional ByVal ControlName As Variant) As Variant
+&apos;&apos;&apos; Return either
+&apos;&apos;&apos; - the list of the controls contained in the dialog
+&apos;&apos;&apos; - a dialog control object based on its name
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; ControlName: a valid control name as a case-sensitive string. If absent the list is returned
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; A zero-base array of strings if ControlName is absent
+&apos;&apos;&apos; An instance of the SF_DialogControl class if ControlName exists
+&apos;&apos;&apos; Exceptions:
+&apos;&apos;&apos; ControlName is invalid
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Dim myDialog As Object, myList As Variant, myControl As Object
+&apos;&apos;&apos; Set myDialog = CreateScriptService(&quot;SFDialogs.Dialog&quot;, Container, Library, DialogName)
+&apos;&apos;&apos; myList = myDialog.Controls()
+&apos;&apos;&apos; Set myControl = myDialog.Controls(&quot;myTextBox&quot;)
+
+Dim oControl As Object &apos; The new control class instance
+Dim lIndexOfNames As Long &apos; Index in ElementNames array. Used to access _ControlCache
+Dim vControl As Variant &apos; Alias of _ControlCache entry
+Const cstThisSub = &quot;SFDialogs.Dialog.Controls&quot;
+Const cstSubArgs = &quot;[ControlName]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+Check:
+ If IsMissing(ControlName) Or IsEmpty(ControlName) Then ControlName = &quot;&quot;
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not _IsStillAlive() Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(ControlName, &quot;ControlName&quot;, V_STRING) Then GoTo Finally
+ End If
+
+Try:
+ If Len(ControlName) = 0 Then
+ Controls = _DialogModel.getElementNames()
+ Else
+ If Not _DialogModel.hasByName(ControlName) Then GoTo CatchNotFound
+ lIndexOfNames = ScriptForge.IndexOf(_DialogModel.getElementNames(), ControlName, CaseSensitive := True)
+ &apos; Reuse cache when relevant
+ vControl = _ControlCache(lIndexOfNames)
+ If IsEmpty(vControl) Then
+ &apos; Create the new dialog control class instance
+ Set oControl = New SF_DialogControl
+ With oControl
+ ._Name = ControlName
+ Set .[Me] = oControl
+ Set .[_Parent] = [Me]
+ ._IndexOfNames = ScriptForge.IndexOf(_DialogModel.getElementNames(), ControlName, CaseSensitive := True)
+ ._DialogName = _Name
+ Set ._ControlModel = _DialogModel.getByName(ControlName)
+ Set ._ControlView = _DialogControl.getControl(ControlName)
+ ._Initialize()
+ End With
+ Else
+ Set oControl = vControl
+ End If
+ Set Controls = oControl
+ End If
+
+Finally:
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+CatchNotFound:
+ ScriptForge.SF_Utils._Validate(ControlName, &quot;ControlName&quot;, V_STRING, _DialogModel.getElementNames())
+ GoTo Finally
+End Function &apos; SFDialogs.SF_Dialog.Controls
+
+REM -----------------------------------------------------------------------------
+Public Sub EndExecute(Optional ByVal ReturnValue As Variant)
+&apos;&apos;&apos; Ends the display of a modal dialog and gives back the argument
+&apos;&apos;&apos; as return value for the current Execute() action
+&apos;&apos;&apos; EndExecute is usually contained in the processing of a macro
+&apos;&apos;&apos; triggered by a dialog or control event
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; ReturnValue: must be numeric. The value passed to the running Execute() method
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Sub OnEvent(poEvent As Variant)
+&apos;&apos;&apos; Dim oDlg As Object
+&apos;&apos;&apos; Set oDlg = CreateScriptService(&quot;SFDialogs.DialogEvent&quot;, poEvent)
+&apos;&apos;&apos; oDlg.EndExecute(25)
+&apos;&apos;&apos; End Sub
+
+Dim lExecute As Long &apos; Alias of ReturnValue
+Const cstThisSub = &quot;SFDialogs.Dialog.EndExecute&quot;
+Const cstSubArgs = &quot;ReturnValue&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+Check:
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not _IsStillAlive() Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(ReturnValue, &quot;ReturnValue&quot;, V_NUMERIC) Then GoTo Finally
+ End If
+
+Try:
+ lExecute = CLng(ReturnValue)
+ Call _DialogControl.endDialog(lExecute)
+
+Finally:
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Sub
+Catch:
+ GoTo Finally
+End Sub &apos; SFDialogs.SF_Dialog.EndExecute
+
+REM -----------------------------------------------------------------------------
+Public Function Execute(Optional ByVal Modal As Variant) As Long
+&apos;&apos;&apos; Display the dialog and wait for its termination by the user
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Modal: False when non-modal dialog. Default = True
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; 0 = Cancel button pressed
+&apos;&apos;&apos; 1 = OK button pressed
+&apos;&apos;&apos; Otherwise: the dialog stopped with an EndExecute statement executed from a dialog or control event
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Dim oDlg As Object, lReturn As Long
+&apos;&apos;&apos; Set oDlg = CreateScriptService(,, &quot;myDialog&quot;) &apos; Dialog stored in current document&apos;s standard library
+&apos;&apos;&apos; lReturn = oDlg.Execute()
+&apos;&apos;&apos; Select Case lReturn
+
+Dim lExecute As Long &apos; Return value
+Const cstThisSub = &quot;SFDialogs.Dialog.Execute&quot;
+Const cstSubArgs = &quot;[Modal=True]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ lExecute = -1
+
+Check:
+ If IsMissing(Modal) Or IsEmpty(Modal) Then Modal = True
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not _IsStillAlive() Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(Modal, &quot;Modal&quot;, V_BOOLEAN) Then GoTo Finally
+ End If
+
+Try:
+ If Modal Then
+ _Modal = True
+ _Displayed = True
+ lExecute = _DialogControl.execute()
+ Select Case lExecute
+ Case 1 : lExecute = OKBUTTON
+ Case 0 : lExecute = CANCELBUTTON
+ Case Else
+ End Select
+ _Displayed = False
+ Else
+ _Modal = False
+ _Displayed = True
+ _DialogModel.DesktopAsParent = True
+ _DialogControl.setVisible(True)
+ lExecute = 0
+ End If
+
+Finally:
+ Execute = lExecute
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_Dialog.Execute
+
+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:
+&apos;&apos;&apos; PropertyName: the name of the property as a string
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The actual value of the property
+&apos;&apos;&apos; Exceptions:
+&apos;&apos;&apos; ARGUMENTERROR The property does not exist
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; oDlg.GetProperty(&quot;Caption&quot;)
+
+Const cstThisSub = &quot;SFDialogs.Dialog.GetProperty&quot;
+Const cstSubArgs = &quot;&quot;
+
+ If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ GetProperty = Null
+
+Check:
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
+ End If
+
+Try:
+ GetProperty = _PropertyGet(PropertyName)
+
+Finally:
+ SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_Dialog.GetProperty
+
+REM -----------------------------------------------------------------------------
+Public Function GetTextsFromL10N(Optional ByRef L10N As Variant) As Boolean
+&apos;&apos;&apos; Replace all fixed text strings of a dialog by their localized version
+&apos;&apos;&apos; Replaced texts are:
+&apos;&apos;&apos; - the title of the dialog
+&apos;&apos;&apos; - the caption associated with next control types: Button, CheckBox, FixedLine, FixedText, GroupBox and RadioButton
+&apos;&apos;&apos; - the content of list- and comboboxes
+&apos;&apos;&apos; - the tip- or helptext displayed when the mouse is hovering the control
+&apos;&apos;&apos; The current method has a twin method ScriptForge.SF_L10N.AddTextsFromDialog
+&apos;&apos;&apos; The current method is probably run before the Execute() method
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; L10N : a &quot;L10N&quot; service instance created with CreateScriptService(&quot;L10N&quot;)
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; True when successful
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; Dim myPO As Object, oDlg As Object
+&apos;&apos;&apos; Set oDlg = CreateScriptService(&quot;Dialog&quot;, &quot;GlobalScope&quot;, &quot;XrayTool&quot;, &quot;DlgXray&quot;)
+&apos;&apos;&apos; Set myPO = CreateScriptService(&quot;L10N&quot;, &quot;C:\myPOFiles\&quot;, &quot;fr-BE&quot;)
+&apos;&apos;&apos; oDlg.GetTextsFromL10N(myPO)
+
+Dim bGet As Boolean &apos; Return value
+Dim vControls As Variant &apos; Array of control names
+Dim sControl As String &apos; A single control name
+Dim oControl As Object &apos; SFDialogs.DialogControl
+Dim sText As String &apos; The text found in the dialog
+Dim sTranslation As String &apos; The translated text got from the dictionary
+Dim vSource As Variant &apos; RowSource property of dialog control as an array
+Dim bChanged As Boolean &apos; True when at least 1 item of a RowSource is modified
+Dim i As Long
+
+Const cstThisSub = &quot;SFDialogs.Dialog.GetTextsFromL10N&quot;
+Const cstSubArgs = &quot;L10N&quot;
+
+ If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bGet = False
+
+Check:
+ If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not SF_Utils._Validate(L10N, &quot;L10N&quot;, V_OBJECT, , , &quot;L10N&quot;) Then GoTo Finally
+ End If
+
+Try:
+ &apos; Get the dialog title
+ sText = Caption
+ If Len(sText) &gt; 0 Then
+ sTranslation = L10N._(sText)
+ If sText &lt;&gt; sTranslation Then Caption = sTranslation
+ End If
+ &apos; Scan all controls
+ vControls = Controls()
+ For Each sControl In vControls
+ Set oControl = Controls(sControl)
+ With oControl
+ &apos; Extract fixed texts
+ sText = .Caption
+ If Len(sText) &gt; 0 Then
+ sTranslation = L10N._(sText)
+ If sText &lt;&gt; sTranslation Then .Caption = sTranslation
+ End If
+ vSource = .RowSource &apos; List and comboboxes only
+ If IsArray(vSource) Then
+ bChanged = False
+ For i = 0 To UBound(vSource)
+ If Len(vSource(i)) &gt; 0 Then
+ sTranslation = L10N._(vSource(i))
+ If sTranslation &lt;&gt; vSource(i) Then
+ bChanged = True
+ vSource(i) = sTranslation
+ End If
+ End If
+ Next i
+ &apos; Rewrite if at least 1 item has been modified by the translation process
+ If bChanged Then .RowSource = vSource
+ End If
+ sText = .TipText
+ If Len(sText) &gt; 0 Then
+ sTranslation = L10N._(sText)
+ If sText &lt;&gt; sTranslation Then .TipText = sTranslation
+ End If
+ End With
+ Next sControl
+
+ bGet = True
+
+Finally:
+ GetTextsFromL10N = bGet
+ SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_Dialog.GetTextsFromL10N
+
+REM -----------------------------------------------------------------------------
+Public Function Methods() As Variant
+&apos;&apos;&apos; Return the list of public methods of the Model service as an array
+
+ Methods = Array( _
+ &quot;Activate&quot; _
+ , &quot;Center&quot; _
+ , &quot;Controls&quot; _
+ , &quot;EndExecute&quot; _
+ , &quot;Execute&quot; _
+ , &quot;GetTextsFromL10N&quot; _
+ , &quot;Resize&quot; _
+ , &quot;Terminate&quot; _
+ )
+
+End Function &apos; SFDialogs.SF_Dialog.Methods
+
+REM -----------------------------------------------------------------------------
+Public Function Properties() As Variant
+&apos;&apos;&apos; Return the list or properties of the Dialog class as an array
+
+ Properties = Array( _
+ &quot;Caption&quot; _
+ , &quot;Height&quot; _
+ , &quot;Modal&quot; _
+ , &quot;Name&quot; _
+ , &quot;OnFocusGained&quot; _
+ , &quot;OnFocusLost&quot; _
+ , &quot;OnKeyPressed&quot; _
+ , &quot;OnKeyReleased&quot; _
+ , &quot;OnMouseDragged&quot; _
+ , &quot;OnMouseEntered&quot; _
+ , &quot;OnMouseExited&quot; _
+ , &quot;OnMouseMoved&quot; _
+ , &quot;OnMousePressed&quot; _
+ , &quot;OnMouseReleased&quot; _
+ , &quot;Page&quot; _
+ , &quot;Visible&quot; _
+ , &quot;Width&quot; _
+ , &quot;XDialogModel&quot; _
+ , &quot;XDialogView&quot; _
+ )
+
+End Function &apos; SFDialogs.SF_Dialog.Properties
+
+REM -----------------------------------------------------------------------------
+Public Function Resize(Optional ByVal Left As Variant _
+ , Optional ByVal Top As Variant _
+ , Optional ByVal Width As Variant _
+ , Optional ByVal Height As Variant _
+ ) As Boolean
+&apos;&apos;&apos; Move the top-left corner of a dialog to new coordinates and/or modify its dimensions
+&apos;&apos;&apos; All distances are expressed in 1/100 mm.
+&apos;&apos;&apos; Without arguments, the method resets the initial dimensions
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Left : the horizontal distance from the top-left corner
+&apos;&apos;&apos; Top : the vertical distance from the top-left corner
+&apos;&apos;&apos; Width : the horizontal width of the rectangle containing the Dialog
+&apos;&apos;&apos; Height : the vertical height of the rectangle containing the Dialog
+&apos;&apos;&apos; Negative or missing arguments are left unchanged
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; True when successful
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; oDialog.Resize(1000, 2000, Height := 6000) &apos; Width is not changed
+
+Dim bResize As Boolean &apos; Return value
+Dim oPosSize As Object &apos; com.sun.star.awt.Rectangle
+Dim iFlags As Integer &apos; com.sun.star.awt.PosSize constants
+Const cstThisSub = &quot;SFDialogs.Dialog.Resize&quot;
+Const cstSubArgs = &quot;[Left], [Top], [Width], [Height]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bResize = False
+
+Check:
+ If IsMissing(Left) Or IsEmpty(Left) Then Left = -1
+ If IsMissing(Top) Or IsEmpty(Top) Then Top = -1
+ If IsMissing(Height) Or IsEmpty(Height) Then Height = -1
+ If IsMissing(Width) Or IsEmpty(Width) Then Width = -1
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(Left, &quot;Left&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(Top, &quot;Top&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(Width, &quot;Width&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(Height, &quot;Height&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ End If
+
+Try:
+ With _DialogControl
+ Set oPosSize = .getPosSize()
+ &apos; Reset factory settings
+ If Left = -1 And Top = -1 And Width = -1 And Height = -1 Then
+ &apos;Left = _Left &apos; Initial positions determination is unstable
+ &apos;Top = _Top
+ Width = _Width
+ Height = _Height
+ End If
+ &apos; Trace the elements to change
+ iFlags = 0
+ With com.sun.star.awt.PosSize
+ If Left &gt;= 0 Then iFlags = iFlags + .X Else Left = oPosSize.X
+ If Top &gt;= 0 Then iFlags = iFlags + .Y Else Top = oPosSize.Y
+ If Width &gt; 0 Then iFlags = iFlags + .WIDTH Else Width = oPosSize.Width
+ If Height &gt; 0 Then iFlags = iFlags + .HEIGHT Else Height = oPosSize.Height
+ End With
+ &apos; Rewrite
+ If iFlags &gt; 0 Then .setPosSize(CLng(Left), CLng(Top), CLng(Width), CLng(Height), iFlags)
+ End With
+ bResize = True
+
+Finally:
+ Resize = bResize
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SF_Documents.SF_Dialog.Resize
+
+REM -----------------------------------------------------------------------------
+Public Function SetProperty(Optional ByVal PropertyName As Variant _
+ , Optional ByRef Value As Variant _
+ ) As Boolean
+&apos;&apos;&apos; Set a new value to the given property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; PropertyName: the name of the property as a string
+&apos;&apos;&apos; Value: its new value
+&apos;&apos;&apos; Exceptions
+&apos;&apos;&apos; ARGUMENTERROR The property does not exist
+
+Const cstThisSub = &quot;SFDialogs.Dialog.SetProperty&quot;
+Const cstSubArgs = &quot;PropertyName, Value&quot;
+
+ If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ SetProperty = False
+
+Check:
+ If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
+ End If
+
+Try:
+ SetProperty = _PropertySet(PropertyName, Value)
+
+Finally:
+ SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_Dialog.SetProperty
+
+REM -----------------------------------------------------------------------------
+Public Function Terminate() As Boolean
+&apos;&apos;&apos; Terminate the dialog service for the current dialog instance
+&apos;&apos;&apos; After termination any action on the current instance will be ignored
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; True if termination is successful
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Dim oDlg As Object, lReturn As Long
+&apos;&apos;&apos; Set oDlg = CreateScriptService(,, &quot;myDialog&quot;) &apos; Dialog stored in current document&apos;s standard library
+&apos;&apos;&apos; lreturn = oDlg.Execute()
+&apos;&apos;&apos; Select Case lReturn
+&apos;&apos;&apos; &apos; ...
+&apos;&apos;&apos; End Select
+&apos;&apos;&apos; oDlg.Terminate()
+
+Dim bTerminate As Boolean &apos; Return value
+Const cstThisSub = &quot;SFDialogs.Dialog.Terminate&quot;
+Const cstSubArgs = &quot;&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bTerminate = False
+
+Check:
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not _IsStillAlive() Then GoTo Finally
+ End If
+Try:
+ _DialogControl.dispose()
+ Set _DialogControl = Nothing
+ SF_Register._CleanCacheEntry(_CacheIndex)
+ _CacheIndex = -1
+ Dispose()
+
+ bTerminate = True
+
+Finally:
+ Terminate = bTerminate
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_Dialog.Terminate
+
+REM =========================================================== PRIVATE FUNCTIONS
+
+REM -----------------------------------------------------------------------------
+Public Function _GetEventName(ByVal psProperty As String) As String
+&apos;&apos;&apos; Return the LO internal event name derived from the SF property name
+&apos;&apos;&apos; The SF property name is not case sensitive, while the LO name is case-sensitive
+&apos; Corrects the typo on ErrorOccur(r?)ed, if necessary
+
+Dim vProperties As Variant &apos; Array of class properties
+Dim sProperty As String &apos; Correctly cased property name
+
+ vProperties = Properties()
+ sProperty = vProperties(ScriptForge.SF_Array.IndexOf(vProperties, psProperty, SortOrder := &quot;ASC&quot;))
+
+ _GetEventName = LCase(Mid(sProperty, 3, 1)) &amp; Right(sProperty, Len(sProperty) - 3)
+
+End Function &apos; SFDialogs.SF_Dialog._GetEventName
+
+REM -----------------------------------------------------------------------------
+Private Function _GetListener(ByVal psEventName As String) As String
+&apos;&apos;&apos; Getting/Setting macros triggered by events requires a Listener-EventName pair
+&apos;&apos;&apos; Return the X...Listener corresponding with the event name in argument
+
+ Select Case UCase(psEventName)
+ Case UCase(&quot;OnFocusGained&quot;), UCase(&quot;OnFocusLost&quot;)
+ _GetListener = &quot;XFocusListener&quot;
+ Case UCase(&quot;OnKeyPressed&quot;), UCase(&quot;OnKeyReleased&quot;)
+ _GetListener = &quot;XKeyListener&quot;
+ Case UCase(&quot;OnMouseDragged&quot;), UCase(&quot;OnMouseMoved&quot;)
+ _GetListener = &quot;XMouseMotionListener&quot;
+ Case UCase(&quot;OnMouseEntered&quot;), UCase(&quot;OnMouseExited&quot;), UCase(&quot;OnMousePressed&quot;), UCase(&quot;OnMouseReleased&quot;)
+ _GetListener = &quot;XMouseListener&quot;
+ Case Else
+ _GetListener = &quot;&quot;
+ End Select
+
+End Function &apos; SFDialogs.SF_Dialog._GetListener
+
+REM -----------------------------------------------------------------------------
+Public Sub _Initialize()
+&apos;&apos;&apos; Complete the object creation process:
+&apos;&apos;&apos; - Initialization of private members
+&apos;&apos;&apos; - Creation of the dialog graphical interface
+&apos;&apos;&apos; - Addition of the new object in the Dialogs buffer
+&apos;&apos;&apos; - Initialisation of persistent storage for controls
+
+Dim oPosSize As Object &apos; com.sun.star.awt.Rectangle
+
+Try:
+ &apos; Keep reference to model
+ Set _DialogModel = _DialogControl.Model
+
+ &apos; Store initial position and dimensions
+ Set oPosSize = _DialogControl.getPosSize()
+ With oPosSize
+ _Left = .X
+ _Top = .Y
+ _Width = .Width
+ _Height = .Height
+ End With
+
+ &apos; Add dialog reference to cache
+ _CacheIndex = SF_Register._AddDialogToCache(_DialogControl, [Me])
+
+ &apos; Size the persistent storage
+ _ControlCache = Array()
+ ReDim _ControlCache(0 To UBound(_DialogModel.getElementNames()))
+
+Finally:
+ Exit Sub
+End Sub &apos; SFDialogs.SF_Dialog._Initialize
+
+REM -----------------------------------------------------------------------------
+Private Function _IsStillAlive(Optional ByVal pbError As Boolean) As Boolean
+&apos;&apos;&apos; Return True if the dialog service is still active
+&apos;&apos;&apos; If dead the actual instance is disposed. The execution is cancelled when pbError = True (default)
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; pbError: if True (default), raise a fatal error
+
+Dim bAlive As Boolean &apos; Return value
+Dim sDialog As String &apos; Alias of DialogName
+
+Check:
+ On Local Error GoTo Catch &apos; Anticipate DisposedException errors or alike
+ If IsMissing(pbError) Then pbError = True
+
+Try:
+ bAlive = ( Not IsNull(_DialogProvider) And Not IsNull(_DialogControl) )
+ If Not bAlive Then GoTo Catch
+
+Finally:
+ _IsStillAlive = bAlive
+ Exit Function
+Catch:
+ bAlive = False
+ On Error GoTo 0
+ sDialog = _Name
+ Dispose()
+ If pbError Then ScriptForge.SF_Exception.RaiseFatal(DIALOGDEADERROR, sDialog)
+ GoTo Finally
+End Function &apos; SFDialogs.SF_Dialog._IsStillAlive
+
+REM -----------------------------------------------------------------------------
+Private Function _PropertyGet(Optional ByVal psProperty As String) As Variant
+&apos;&apos;&apos; Return the value of the named property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psProperty: the name of the property
+
+Static oSession As Object &apos; Alias of SF_Session
+Dim oDialogEvents As Object &apos; com.sun.star.container.XNameContainer
+Dim sEventName As String &apos; Internal event name
+Dim cstThisSub As String
+Const cstSubArgs = &quot;&quot;
+
+ cstThisSub = &quot;SFDialogs.Dialog.get&quot; &amp; psProperty
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+ ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+ If Not _IsStillAlive() Then GoTo Finally
+
+ If IsNull(oSession) Then Set oSession = ScriptForge.SF_Services.CreateScriptService(&quot;Session&quot;)
+ Select Case UCase(psProperty)
+ Case UCase(&quot;Caption&quot;)
+ If oSession.HasUNOProperty(_DialogModel, &quot;Title&quot;) Then _PropertyGet = _DialogModel.Title
+ Case UCase(&quot;Height&quot;)
+ If oSession.HasUNOProperty(_DialogModel, &quot;Height&quot;) Then _PropertyGet = _DialogModel.Height
+ Case UCase(&quot;Modal&quot;)
+ _PropertyGet = _Modal
+ Case UCase(&quot;Name&quot;)
+ _PropertyGet = _Name
+ Case UCase(&quot;OnFocusGained&quot;), UCase(&quot;OnFocusLost&quot;), UCase(&quot;OnKeyPressed&quot;), UCase(&quot;OnKeyReleased&quot;) _
+ , UCase(&quot;OnMouseDragged&quot;), UCase(&quot;OnMouseEntered&quot;), UCase(&quot;OnMouseExited&quot;), UCase(&quot;OnMouseMoved&quot;) _
+ , UCase(&quot;OnMousePressed&quot;), UCase(&quot;OnMouseReleased&quot;)
+ Set oDialogEvents = _DialogModel.getEvents()
+ sEventName = &quot;com.sun.star.awt.&quot; &amp; _GetListener(psProperty) &amp; &quot;::&quot; &amp; _GetEventName(psProperty)
+ If oDialogEvents.hasByName(sEventName) Then
+ _PropertyGet = oDialogEvents.getByName(sEventName).ScriptCode
+ Else
+ _PropertyGet = &quot;&quot;
+ End If
+ Case UCase(&quot;Page&quot;)
+ If oSession.HasUNOProperty(_DialogModel, &quot;Step&quot;) Then _PropertyGet = _DialogModel.Step
+ Case UCase(&quot;Visible&quot;)
+ If oSession.HasUnoMethod(_DialogControl, &quot;isVisible&quot;) Then _PropertyGet = CBool(_DialogControl.isVisible())
+ Case UCase(&quot;Width&quot;)
+ If oSession.HasUNOProperty(_DialogModel, &quot;Width&quot;) Then _PropertyGet = _DialogModel.Width
+ Case UCase(&quot;XDialogModel&quot;)
+ Set _PropertyGet = _DialogModel
+ Case UCase(&quot;XDialogView&quot;)
+ Set _PropertyGet = _DialogControl
+ Case Else
+ _PropertyGet = Null
+ End Select
+
+Finally:
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_Dialog._PropertyGet
+
+REM -----------------------------------------------------------------------------
+Private Function _PropertySet(Optional ByVal psProperty As String _
+ , Optional ByVal pvValue As Variant _
+ ) As Boolean
+&apos;&apos;&apos; Set the new value of the named property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psProperty: the name of the property
+&apos;&apos;&apos; pvValue: the new value of the given property
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; True if successful
+
+Dim bSet As Boolean &apos; Return value
+Static oSession As Object &apos; Alias of SF_Session
+Dim cstThisSub As String
+Const cstSubArgs = &quot;Value&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bSet = False
+
+ cstThisSub = &quot;SFDialogs.Dialog.set&quot; &amp; psProperty
+ ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+ If Not _IsStillAlive() Then GoTo Finally
+
+ If IsNull(oSession) Then Set oSession = ScriptForge.SF_Services.CreateScriptService(&quot;Session&quot;)
+ bSet = True
+ Select Case UCase(psProperty)
+ Case UCase(&quot;Caption&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Caption&quot;, V_STRING) Then GoTo Finally
+ If oSession.HasUNOProperty(_DialogModel, &quot;Title&quot;) Then _DialogModel.Title = pvValue
+ Case UCase(&quot;Height&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Height&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ If oSession.HasUNOProperty(_DialogModel, &quot;Height&quot;) Then _DialogModel.Height = pvValue
+ Case UCase(&quot;Page&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Page&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ If oSession.HasUNOProperty(_DialogModel, &quot;Step&quot;) Then _DialogModel.Step = CLng(pvValue)
+ Case UCase(&quot;Visible&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Visible&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+ If oSession.HasUnoMethod(_DialogControl, &quot;setVisible&quot;) Then _DialogControl.setVisible(pvValue)
+ Case UCase(&quot;Width&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Width&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ If oSession.HasUNOProperty(_DialogModel, &quot;Width&quot;) Then _DialogModel.Width = pvValue
+ Case Else
+ bSet = False
+ End Select
+
+Finally:
+ _PropertySet = bSet
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_Dialog._PropertySet
+
+REM -----------------------------------------------------------------------------
+Private Function _Repr() As String
+&apos;&apos;&apos; Convert the Model instance to a readable string, typically for debugging purposes (DebugPrint ...)
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Return:
+&apos;&apos;&apos; &quot;[DIALOG]: Container.Library.Name&quot;
+
+ _Repr = &quot;[DIALOG]: &quot; &amp; _Container &amp; &quot;.&quot; &amp; _Library &amp; &quot;.&quot; &amp; _Name
+
+End Function &apos; SFDialogs.SF_Dialog._Repr
+
+REM ============================================ END OF SFDIALOGS.SF_DIALOG
+</script:module> \ No newline at end of file
diff --git a/wizards/source/sfdialogs/SF_DialogControl.xba b/wizards/source/sfdialogs/SF_DialogControl.xba
new file mode 100644
index 000000000..f4a0891d9
--- /dev/null
+++ b/wizards/source/sfdialogs/SF_DialogControl.xba
@@ -0,0 +1,2084 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
+<script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_DialogControl" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
+REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
+REM === The SFDialogs library is one of the associated libraries. ===
+REM === Full documentation is available on https://help.libreoffice.org/ ===
+REM =======================================================================================================================
+
+Option Compatible
+Option ClassModule
+
+Option Explicit
+
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+&apos;&apos;&apos; SF_DialogControl
+&apos;&apos;&apos; ================
+&apos;&apos;&apos; Manage the controls belonging to a dialog defined with the Basic IDE
+&apos;&apos;&apos; Each instance of the current class represents a single control within a dialog box
+&apos;&apos;&apos;
+&apos;&apos;&apos; The focus is clearly set on getting and setting the values displayed by the controls of the dialog box,
+&apos;&apos;&apos; not on their formatting. The latter is easily accessible via the XControlModel and XControlView
+&apos;&apos;&apos; UNO objects.
+&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 types TreeControl and TableControl
+&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 AddSubNode), or
+&apos;&apos;&apos; - with a set of branches at once (AddSubtree)
+&apos;&apos;&apos; Additionally populating a TreeControl can be done statically or dynamically
+&apos;&apos;&apos;
+&apos;&apos;&apos; With the method SetTableData(), feed a tablecontrol with a sortable and selectable
+&apos;&apos;&apos; array of data. Columns and rows may receive a header. Column widths are adjusted manually by the user or
+&apos;&apos;&apos; with the same method. Alignments can be set as well by script.
+&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)
+&apos;&apos;&apos; Set myControl = myDialog.Controls(&quot;myTextBox&quot;)
+&apos;&apos;&apos; myControl.Value = &quot;Dialog started at &quot; &amp; Now()
+&apos;&apos;&apos; myDialog.Execute()
+&apos;&apos;&apos; &apos; ... process the controls actual values
+&apos;&apos;&apos; myDialog.Terminate()
+&apos;&apos;&apos;
+&apos;&apos;&apos; Detailed user documentation:
+&apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_dialogcontrol.html?DbPAR=BASIC
+&apos;&apos;&apos;
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+
+REM ================================================================== EXCEPTIONS
+
+Private Const CONTROLTYPEERROR = &quot;CONTROLTYPEERROR&quot;
+Private Const TEXTFIELDERROR = &quot;TEXTFIELDERROR&quot;
+
+REM ============================================================= PRIVATE MEMBERS
+
+Private [Me] As Object
+Private [_Parent] As Object
+Private ObjectType As String &apos; Must be DIALOGCONTROL
+Private ServiceName As String
+
+&apos; Control naming
+Private _Name As String
+Private _IndexOfNames As Long &apos; Index in ElementNames array. Used to access SF_Dialog._ControlCache
+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
+Private _GridColumnModel As Object &apos; com.sun.star.awt.grid.XGridColumnModel
+Private _GridDataModel As Object &apos; com.sun.star.awt.grid.XGridDataModel
+
+&apos; Control attributes
+Private _ImplementationName As String
+Private _ControlType As String &apos; One of the CTLxxx constants
+
+&apos; Tree control on-select and on-expand attributes
+&apos; Tree controls may be associated with events not defined in the Basic IDE
+Private _OnNodeSelected As String &apos; Script to invoke when a node is selected
+Private _OnNodeExpanded As String &apos; Script to invoke when a node is expanded
+Private _SelectListener As Object &apos; com.sun.star.view.XSelectionChangeListener
+Private _ExpandListener As Object &apos; com.sun.star.awt.tree.XTreeExpansionListener
+
+&apos; Table control attributes
+Private _ColumnWidths As Variant &apos; Array of column widths
+
+REM ============================================================ MODULE CONSTANTS
+
+Private Const CTLBUTTON = &quot;Button&quot;
+Private Const CTLCHECKBOX = &quot;CheckBox&quot;
+Private Const CTLCOMBOBOX = &quot;ComboBox&quot;
+Private Const CTLCURRENCYFIELD = &quot;CurrencyField&quot;
+Private Const CTLDATEFIELD = &quot;DateField&quot;
+Private Const CTLFILECONTROL = &quot;FileControl&quot;
+Private Const CTLFIXEDLINE = &quot;FixedLine&quot;
+Private Const CTLFIXEDTEXT = &quot;FixedText&quot;
+Private Const CTLFORMATTEDFIELD = &quot;FormattedField&quot;
+Private Const CTLGROUPBOX = &quot;GroupBox&quot;
+Private Const CTLIMAGECONTROL = &quot;ImageControl&quot;
+Private Const CTLLISTBOX = &quot;ListBox&quot;
+Private Const CTLNUMERICFIELD = &quot;NumericField&quot;
+Private Const CTLPATTERNFIELD = &quot;PatternField&quot;
+Private Const CTLPROGRESSBAR = &quot;ProgressBar&quot;
+Private Const CTLRADIOBUTTON = &quot;RadioButton&quot;
+Private Const CTLSCROLLBAR = &quot;ScrollBar&quot;
+Private Const CTLTABLECONTROL = &quot;TableControl&quot;
+Private Const CTLTEXTFIELD = &quot;TextField&quot;
+Private Const CTLTIMEFIELD = &quot;TimeField&quot;
+Private Const CTLTREECONTROL = &quot;TreeControl&quot;
+
+REM ====================================================== CONSTRUCTOR/DESTRUCTOR
+
+REM -----------------------------------------------------------------------------
+Private Sub Class_Initialize()
+ Set [Me] = Nothing
+ Set [_Parent] = Nothing
+ ObjectType = &quot;DIALOGCONTROL&quot;
+ ServiceName = &quot;SFDialogs.DialogControl&quot;
+ _Name = &quot;&quot;
+ _IndexOfNames = -1
+ _DialogName = &quot;&quot;
+ Set _ControlModel = Nothing
+ Set _ControlView = Nothing
+ Set _TreeDataModel = Nothing
+ Set _GridColumnModel = Nothing
+ Set _GridDataModel = Nothing
+ _ImplementationName = &quot;&quot;
+ _ControlType = &quot;&quot;
+ _OnNodeSelected = &quot;&quot;
+ _OnNodeExpanded = &quot;&quot;
+ Set _SelectListener = Nothing
+ Set _ExpandListener = Nothing
+ _ColumnWidths = Array()
+End Sub &apos; SFDialogs.SF_DialogControl Constructor
+
+REM -----------------------------------------------------------------------------
+Private Sub Class_Terminate()
+ Call Class_Initialize()
+End Sub &apos; SFDialogs.SF_DialogControl Destructor
+
+REM -----------------------------------------------------------------------------
+Public Function Dispose() As Variant
+ Call Class_Terminate()
+ Set Dispose = Nothing
+End Function &apos; SFDialogs.SF_DialogControl Explicit Destructor
+
+REM ================================================================== PROPERTIES
+
+REM -----------------------------------------------------------------------------
+Property Get Cancel() As Variant
+&apos;&apos;&apos; The Cancel property specifies if a command button has or not the behaviour of a Cancel button.
+ Cancel = _PropertyGet(&quot;Cancel&quot;, False)
+End Property &apos; SFDialogs.SF_DialogControl.Cancel (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Cancel(Optional ByVal pvCancel As Variant)
+&apos;&apos;&apos; Set the updatable property Cancel
+ _PropertySet(&quot;Cancel&quot;, pvCancel)
+End Property &apos; SFDialogs.SF_DialogControl.Cancel (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Caption() As Variant
+&apos;&apos;&apos; The Caption property refers to the text associated with the control
+ Caption = _PropertyGet(&quot;Caption&quot;, &quot;&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.Caption (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Caption(Optional ByVal pvCaption As Variant)
+&apos;&apos;&apos; Set the updatable property Caption
+ _PropertySet(&quot;Caption&quot;, pvCaption)
+End Property &apos; SFDialogs.SF_DialogControl.Caption (let)
+
+REM -----------------------------------------------------------------------------
+Property Get ControlType() As String
+&apos;&apos;&apos; Return the type of the actual control: &quot;CheckBox&quot;, &quot;TextField&quot;, &quot;DateField&quot;, ...
+ ControlType = _PropertyGet(&quot;ControlType&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.ControlType
+
+REM -----------------------------------------------------------------------------
+Property Get CurrentNode() As Variant
+&apos;&apos;&apos; The CurrentNode property returns the currently selected node
+&apos;&apos;&apos; It returns Empty when there is no node selected
+&apos;&apos;&apos; When there are several selections, it returns the topmost node among the selected ones
+ CurrentNode = _PropertyGet(&quot;CurrentNode&quot;, &quot;&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.CurrentNode (get)
+
+REM -----------------------------------------------------------------------------
+Property Let CurrentNode(Optional ByVal pvCurrentNode As Variant)
+&apos;&apos;&apos; Set a single selection in a tree control
+ _PropertySet(&quot;CurrentNode&quot;, pvCurrentNode)
+End Property &apos; SFDialogs.SF_DialogControl.CurrentNode (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Default() As Variant
+&apos;&apos;&apos; The Default property specifies whether a command button is the default (OK) button.
+ Default = _PropertyGet(&quot;Default&quot;, False)
+End Property &apos; SFDialogs.SF_DialogControl.Default (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Default(Optional ByVal pvDefault As Variant)
+&apos;&apos;&apos; Set the updatable property Default
+ _PropertySet(&quot;Default&quot;, pvDefault)
+End Property &apos; SFDialogs.SF_DialogControl.Default (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Enabled() As Variant
+&apos;&apos;&apos; The Enabled property specifies if the control is accessible with the cursor.
+ Enabled = _PropertyGet(&quot;Enabled&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.Enabled (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Enabled(Optional ByVal pvEnabled As Variant)
+&apos;&apos;&apos; Set the updatable property Enabled
+ _PropertySet(&quot;Enabled&quot;, pvEnabled)
+End Property &apos; SFDialogs.SF_DialogControl.Enabled (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Format() As Variant
+&apos;&apos;&apos; The Format property specifies the format in which to display dates and times.
+ Format = _PropertyGet(&quot;Format&quot;, &quot;&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.Format (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Format(Optional ByVal pvFormat As Variant)
+&apos;&apos;&apos; Set the updatable property Format
+&apos;&apos;&apos; NB: Format is read-only for formatted field controls
+ _PropertySet(&quot;Format&quot;, pvFormat)
+End Property &apos; SFDialogs.SF_DialogControl.Format (let)
+
+REM -----------------------------------------------------------------------------
+Property Get ListCount() As Long
+&apos;&apos;&apos; The ListCount property specifies the number of rows in a list box or a combo box
+ ListCount = _PropertyGet(&quot;ListCount&quot;, 0)
+End Property &apos; SFDialogs.SF_DialogControl.ListCount (get)
+
+REM -----------------------------------------------------------------------------
+Property Get ListIndex() As Variant
+&apos;&apos;&apos; The ListIndex property specifies which item is selected in a list box or combo box.
+&apos;&apos;&apos; In case of multiple selection, the index of the first one is returned or only one is set
+ ListIndex = _PropertyGet(&quot;ListIndex&quot;, -1)
+End Property &apos; SFDialogs.SF_DialogControl.ListIndex (get)
+
+REM -----------------------------------------------------------------------------
+Property Let ListIndex(Optional ByVal pvListIndex As Variant)
+&apos;&apos;&apos; Set the updatable property ListIndex
+ _PropertySet(&quot;ListIndex&quot;, pvListIndex)
+End Property &apos; SFDialogs.SF_DialogControl.ListIndex (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Locked() As Variant
+&apos;&apos;&apos; The Locked property specifies if a control is read-only
+ Locked = _PropertyGet(&quot;Locked&quot;, False)
+End Property &apos; SFDialogs.SF_DialogControl.Locked (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Locked(Optional ByVal pvLocked As Variant)
+&apos;&apos;&apos; Set the updatable property Locked
+ _PropertySet(&quot;Locked&quot;, pvLocked)
+End Property &apos; SFDialogs.SF_DialogControl.Locked (let)
+
+REM -----------------------------------------------------------------------------
+Property Get MultiSelect() As Variant
+&apos;&apos;&apos; The MultiSelect property specifies whether a user can make multiple selections in a listbox
+ MultiSelect = _PropertyGet(&quot;MultiSelect&quot;, False)
+End Property &apos; SFDialogs.SF_DialogControl.MultiSelect (get)
+
+REM -----------------------------------------------------------------------------
+Property Let MultiSelect(Optional ByVal pvMultiSelect As Variant)
+&apos;&apos;&apos; Set the updatable property MultiSelect
+ _PropertySet(&quot;MultiSelect&quot;, pvMultiSelect)
+End Property &apos; SFDialogs.SF_DialogControl.MultiSelect (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Name() As String
+&apos;&apos;&apos; Return the name of the actual control
+ Name = _PropertyGet(&quot;Name&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.Name
+
+REM -----------------------------------------------------------------------------
+Property Get OnActionPerformed() As Variant
+&apos;&apos;&apos; Get the script associated with the OnActionPerformed event
+ OnActionPerformed = _PropertyGet(&quot;OnActionPerformed&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnActionPerformed (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnAdjustmentValueChanged() As Variant
+&apos;&apos;&apos; Get the script associated with the OnAdjustmentValueChanged event
+ OnAdjustmentValueChanged = _PropertyGet(&quot;OnAdjustmentValueChanged&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnAdjustmentValueChanged (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnFocusGained() As Variant
+&apos;&apos;&apos; Get the script associated with the OnFocusGained event
+ OnFocusGained = _PropertyGet(&quot;OnFocusGained&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnFocusGained (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnFocusLost() As Variant
+&apos;&apos;&apos; Get the script associated with the OnFocusLost event
+ OnFocusLost = _PropertyGet(&quot;OnFocusLost&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnFocusLost (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnItemStateChanged() As Variant
+&apos;&apos;&apos; Get the script associated with the OnItemStateChanged event
+ OnItemStateChanged = _PropertyGet(&quot;OnItemStateChanged&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnItemStateChanged (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnKeyPressed() As Variant
+&apos;&apos;&apos; Get the script associated with the OnKeyPressed event
+ OnKeyPressed = _PropertyGet(&quot;OnKeyPressed&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnKeyPressed (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnKeyReleased() As Variant
+&apos;&apos;&apos; Get the script associated with the OnKeyReleased event
+ OnKeyReleased = _PropertyGet(&quot;OnKeyReleased&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnKeyReleased (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnMouseDragged() As Variant
+&apos;&apos;&apos; Get the script associated with the OnMouseDragged event
+ OnMouseDragged = _PropertyGet(&quot;OnMouseDragged&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnMouseDragged (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnMouseEntered() As Variant
+&apos;&apos;&apos; Get the script associated with the OnMouseEntered event
+ OnMouseEntered = _PropertyGet(&quot;OnMouseEntered&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnMouseEntered (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnMouseExited() As Variant
+&apos;&apos;&apos; Get the script associated with the OnMouseExited event
+ OnMouseExited = _PropertyGet(&quot;OnMouseExited&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnMouseExited (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnMouseMoved() As Variant
+&apos;&apos;&apos; Get the script associated with the OnMouseMoved event
+ OnMouseMoved = _PropertyGet(&quot;OnMouseMoved&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnMouseMoved (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnMousePressed() As Variant
+&apos;&apos;&apos; Get the script associated with the OnMousePressed event
+ OnMousePressed = _PropertyGet(&quot;OnMousePressed&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnMousePressed (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnMouseReleased() As Variant
+&apos;&apos;&apos; Get the script associated with the OnMouseReleased event
+ OnMouseReleased = _PropertyGet(&quot;OnMouseReleased&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.OnMouseReleased (get)
+
+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;)
+End Property &apos; SFDialogs.SF_DialogControl.OnTextChanged (get)
+
+REM -----------------------------------------------------------------------------
+Property Get Page() As Variant
+&apos;&apos;&apos; A dialog may have several pages that can be traversed by the user step by step. The Page property of the Dialog object defines which page of the dialog is active.
+&apos;&apos;&apos; The Page property of a control defines the page of the dialog on which the control is visible.
+&apos;&apos;&apos; For example, if a control has a page value of 1, it is only visible on page 1 of the dialog.
+&apos;&apos;&apos; If the page value of the dialog is increased from 1 to 2, then all controls with a page value of 1 disappear and all controls with a page value of 2 become visible.
+ Page = _PropertyGet(&quot;Page&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.Page (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Page(Optional ByVal pvPage As Variant)
+&apos;&apos;&apos; Set the updatable property Page
+ _PropertySet(&quot;Page&quot;, pvPage)
+End Property &apos; SFDialogs.SF_DialogControl.Page (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Parent() As Object
+&apos;&apos;&apos; Return the Parent dialog object of the actual control
+ Parent = _PropertyGet(&quot;Parent&quot;, Nothing)
+End Property &apos; SFDialogs.SF_DialogControl.Parent
+
+REM -----------------------------------------------------------------------------
+Property Get Picture() As Variant
+&apos;&apos;&apos; The Picture property specifies a bitmap or other type of graphic to be displayed on the specified control
+ Picture = _PropertyGet(&quot;Picture&quot;, &quot;&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.Picture (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Picture(Optional ByVal pvPicture As Variant)
+&apos;&apos;&apos; Set the updatable property Picture
+ _PropertySet(&quot;Picture&quot;, pvPicture)
+End Property &apos; SFDialogs.SF_DialogControl.Picture (let)
+
+REM -----------------------------------------------------------------------------
+Property Get RootNode() As Variant
+&apos;&apos;&apos; The RootNode property returns the last root node of a tree control
+ RootNode = _PropertyGet(&quot;RootNode&quot;, &quot;&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.RootNode (get)
+
+REM -----------------------------------------------------------------------------
+Property Get RowSource() As Variant
+&apos;&apos;&apos; The RowSource property specifies the data contained in a combobox or a listbox
+&apos;&apos;&apos; as a zero-based array of string values
+ RowSource = _PropertyGet(&quot;RowSource&quot;, &quot;&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.RowSource (get)
+
+REM -----------------------------------------------------------------------------
+Property Let RowSource(Optional ByVal pvRowSource As Variant)
+&apos;&apos;&apos; Set the updatable property RowSource
+ _PropertySet(&quot;RowSource&quot;, pvRowSource)
+End Property &apos; SFDialogs.SF_DialogControl.RowSource (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Text() As Variant
+&apos;&apos;&apos; The Text property specifies the actual content of the control like it is displayed on the screen
+ Text = _PropertyGet(&quot;Text&quot;, &quot;&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.Text (get)
+
+REM -----------------------------------------------------------------------------
+Property Get TipText() As Variant
+&apos;&apos;&apos; The TipText property specifies the text that appears in a screentip when you hold the mouse pointer over a control
+ TipText = _PropertyGet(&quot;TipText&quot;, &quot;&quot;)
+End Property &apos; SFDialogs.SF_DialogControl.TipText (get)
+
+REM -----------------------------------------------------------------------------
+Property Let TipText(Optional ByVal pvTipText As Variant)
+&apos;&apos;&apos; Set the updatable property TipText
+ _PropertySet(&quot;TipText&quot;, pvTipText)
+End Property &apos; SFDialogs.SF_DialogControl.TipText (let)
+
+REM -----------------------------------------------------------------------------
+Property Get TripleState() As Variant
+&apos;&apos;&apos; The TripleState property specifies how a check box will display Null values
+&apos;&apos;&apos; When True, the control will cycle through states for Yes, No, and Null values. The control appears dimmed (grayed) when its Value property is set to Null.
+&apos;&apos;&apos; When False, the control will cycle through states for Yes and No values. Null values display as if they were No values.
+ TripleState = _PropertyGet(&quot;TripleState&quot;, False)
+End Property &apos; SFDialogs.SF_DialogControl.TripleState (get)
+
+REM -----------------------------------------------------------------------------
+Property Let TripleState(Optional ByVal pvTripleState As Variant)
+&apos;&apos;&apos; Set the updatable property TripleState
+ _PropertySet(&quot;TripleState&quot;, pvTripleState)
+End Property &apos; SFDialogs.SF_DialogControl.TripleState (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Value() As Variant
+&apos;&apos;&apos; The Value property specifies the data contained in the control
+ Value = _PropertyGet(&quot;Value&quot;, Empty)
+End Property &apos; SFDialogs.SF_DialogControl.Value (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Value(Optional ByVal pvValue As Variant)
+&apos;&apos;&apos; Set the updatable property Value
+ _PropertySet(&quot;Value&quot;, pvValue)
+End Property &apos; SFDialogs.SF_DialogControl.Value (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Visible() As Variant
+&apos;&apos;&apos; The Visible property specifies if the control is accessible with the cursor.
+ Visible = _PropertyGet(&quot;Visible&quot;, True)
+End Property &apos; SFDialogs.SF_DialogControl.Visible (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Visible(Optional ByVal pvVisible As Variant)
+&apos;&apos;&apos; Set the updatable property Visible
+ _PropertySet(&quot;Visible&quot;, pvVisible)
+End Property &apos; SFDialogs.SF_DialogControl.Visible (let)
+
+REM -----------------------------------------------------------------------------
+Property Get XControlModel() As Object
+&apos;&apos;&apos; The XControlModel property returns the model UNO object of the control
+ XControlModel = _PropertyGet(&quot;XControlModel&quot;, Nothing)
+End Property &apos; SFDialogs.SF_DialogControl.XControlModel (get)
+
+REM -----------------------------------------------------------------------------
+Property Get XControlView() As Object
+&apos;&apos;&apos; The XControlView property returns the view UNO object of the control
+ XControlView = _PropertyGet(&quot;XControlView&quot;, Nothing)
+End Property &apos; SFDialogs.SF_DialogControl.XControlView (get)
+
+REM -----------------------------------------------------------------------------
+Property Get XGridColumnModel() As Object
+&apos;&apos;&apos; The XGridColumnModel property returns the mutable data model UNO object of the tree control
+ XGridColumnModel = _PropertyGet(&quot;XGridColumnModel&quot;, Nothing)
+End Property &apos; SFDialogs.SF_DialogControl.XGridColumnModel (get)
+
+REM -----------------------------------------------------------------------------
+Property Get XGridDataModel() As Object
+&apos;&apos;&apos; The XGridDataModel property returns the mutable data model UNO object of the tree control
+ XGridDataModel = _PropertyGet(&quot;XGridDataModel&quot;, Nothing)
+End Property &apos; SFDialogs.SF_DialogControl.XGridDataModel (get)
+
+REM -----------------------------------------------------------------------------
+Property Get XTreeDataModel() As Object
+&apos;&apos;&apos; The XTreeDataModel property returns the mutable data model UNO object of the tree 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 _ControlType &lt;&gt; CTLTREECONTROL Then GoTo CatchType
+ 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
+CatchType:
+ ScriptForge.SF_Exception.RaiseFatal(CONTROLTYPEERROR, _Name, _DialogName, _ControlType, &quot;AddSubNode&quot;)
+ 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 an 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; When AddSubTree() is called from a Python script, FlatTree may be an array of arrays
+&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; True when successful
+&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, WithDataValue := True)
+
+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 iDims As Integer &apos; Number of dimensions of FlatTree
+Dim lMin1 As Long &apos; Lower bound (rows)
+Dim lMin2 As Long &apos; Lower bounds (cols)
+Dim lMax1 As Long &apos; Upper bound (rows)
+Dim lMax2 As Long &apos; Upper bounds (cols)
+Dim vFlatItem As Variant &apos; A single FlatTree item: FlatTree(i, j)
+Dim vFlatItem2 As Variant &apos; A single FlatTree item
+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 _ControlType &lt;&gt; CTLTREECONTROL Then GoTo CatchType
+ 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;) Then GoTo Catch &apos; Dimensions checked below
+ 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; Determine bounds
+ iDims = ScriptForge.SF_Array.CountDims(FlatTree)
+ Select Case iDims
+ Case -1, 0 : GoTo Catch
+ Case 1 &apos; Called probably from Python
+ lMin1 = LBound(FlatTree, 1) : lMax1 = UBound(FlatTree, 1)
+ If Not IsArray(FlatTree(0)) Then GoTo Catch
+ If UBound(FlatTree(0)) &lt; LBound(FlatTree(0)) Then GoTo Catch &apos; No columns
+ lMin2 = LBound(FlatTree(0)) : lMax2 = UBound(FlatTree(0))
+ Case 2
+ lMin1 = LBound(FlatTree, 1) : lMax1 = UBound(FlatTree, 1)
+ lMin2 = LBound(FlatTree, 2) : lMax2 = UBound(FlatTree, 2)
+ Case Else : GoTo Catch
+ End Select
+
+ &apos; Build a new subtree
+ iStep = Iif(WithDataValue, 2, 1)
+ For i = lMin1 To lMax1
+ bChange = ( i = 0 )
+ &apos; Restart from the parent node at each i-iteration
+ Set oNode = ParentNode
+ For j = lMin2 To lMax2 Step iStep &apos; Array columns
+ If iDims = 1 Then vFlatItem = FlatTree(i)(j) Else vFlatItem = FlatTree(i, j)
+ If vFlatItem = &quot;&quot; Or IsNull(vFlatItem) Or IsEmpty(vFlatItem) Then
+ Set oNode = Nothing
+ Exit For &apos; Exit j-loop
+ End If
+ If Not bChange Then
+ If iDims = 1 Then vFlatItem2 = FlatTree(i - 1)(j) Else vFlatItem2 = FlatTree(i - 1, j)
+ bChange = ( vFlatItem &lt;&gt; vFlatItem2 )
+ End If
+ If bChange Then &apos; Create new subnode at tree depth = j
+ If VarType(vFlatItem) = V_STRING Then sValue = vFlatItem Else sValue = ScriptForge.SF_String.Represent(vFlatItem)
+ Set oNewNode = .createNode(sValue, True)
+ If WithDataValue Then
+ If iDims = 1 Then vFlatItem2 = FlatTree(i)(j + 1) Else vFlatItem2 = FlatTree(i, j + 1)
+ oNewNode.DataValue = vFlatItem2
+ End If
+ 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
+ bSubTree = True
+ End With
+
+Finally:
+ AddSubTree = bSubTree
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+CatchType:
+ ScriptForge.SF_Exception.RaiseFatal(CONTROLTYPEERROR, _Name, _DialogName, _ControlType, &quot;AddSubTree&quot;)
+ 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-existing 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 _ControlType &lt;&gt; CTLTREECONTROL Then GoTo CatchType
+ 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 behaviour 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
+CatchType:
+ ScriptForge.SF_Exception.RaiseFatal(CONTROLTYPEERROR, _Name, _DialogName, _ControlType, &quot;CreateRoot&quot;)
+ GoTo Finally
+End Function &apos; SFDialogs.SF_DialogControl.CreateRoot
+
+REM -----------------------------------------------------------------------------
+Public Function FindNode(Optional ByVal DisplayValue As String _
+ , Optional ByRef DataValue As Variant _
+ , Optional ByVal CaseSensitive As Boolean _
+ ) As Object
+&apos;&apos;&apos; Traverses the tree and find recursively, starting from the root, a node meeting some criteria
+&apos;&apos;&apos; Either (1 match is enough):
+&apos;&apos;&apos; having its DisplayValue like DisplayValue
+&apos;&apos;&apos; having its DataValue = DataValue
+&apos;&apos;&apos; Comparisons may be or not case-sensitive
+&apos;&apos;&apos; The first matching occurrence is returned
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; DisplayValue: the pattern to be matched
+&apos;&apos;&apos; DataValue: a string, a numeric value or a date or Empty (if not applicable)
+&apos;&apos;&apos; CaseSensitive: applicable on both criteria. Default = False
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The found node of type com.sun.star.awt.tree.XMutableTreeNode or Nothing if not found
+&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.FindNode(&quot;*Sophie*&quot;, CaseSensitive := True)
+
+
+Dim oNode As Object &apos; Return value
+Const cstThisSub = &quot;SFDialogs.DialogControl.FindNode&quot;
+Const cstSubArgs = &quot;[DisplayValue=&quot;&quot;&quot;&quot;], [DataValue=Empty], [CaseSensitive=False]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ Set oNode = Nothing
+
+Check:
+ If IsMissing(DisplayValue) Or IsEmpty(DisplayValue) Then DisplayValue = &quot;&quot;
+ If IsMissing(DataValue) Then DataValue = Empty
+ If IsMissing(CaseSensitive) Or IsEmpty(CaseSensitive) Then CaseSensitive = False
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If _ControlType &lt;&gt; CTLTREECONTROL Then GoTo CatchType
+ If Not ScriptForge.SF_Utils._Validate(DisplayValue, &quot;DisplayValue&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(CaseSensitive, &quot;CaseSensitive&quot;, ScriptForge.V_BOOLEAN) Then GoTo Catch
+ End If
+
+Try:
+ Set oNode = _FindNode(_TreeDataModel.getRoot(), DisplayValue, DataValue, CaseSensitive)
+
+Finally:
+ Set FindNode = oNode
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+CatchType:
+ ScriptForge.SF_Exception.RaiseFatal(CONTROLTYPEERROR, _Name, _DialogName, _ControlType, &quot;FindNode&quot;)
+ GoTo Finally
+End Function &apos; SFDialogs.SF_DialogControl.FindNode
+
+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:
+&apos;&apos;&apos; PropertyName: the name of the property as a string
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The actual value of the property
+&apos;&apos;&apos; If the property does not exist, returns Null
+&apos;&apos;&apos; Exceptions:
+&apos;&apos;&apos; see the exceptions of the individual properties
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; myModel.GetProperty(&quot;MyProperty&quot;)
+
+Const cstThisSub = &quot;SFDialogs.DialogControl.GetProperty&quot;
+Const cstSubArgs = &quot;&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ GetProperty = Null
+
+Check:
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
+ End If
+
+Try:
+ GetProperty = _PropertyGet(PropertyName)
+
+Finally:
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_DialogControl.GetProperty
+
+REM -----------------------------------------------------------------------------
+Public Function Methods() As Variant
+&apos;&apos;&apos; Return the list of public methods of the Model service as an array
+
+ Methods = Array( _
+ &quot;AddSubNode&quot; _
+ , &quot;AddSubTree&quot; _
+ , &quot;CreateRoot&quot; _
+ , &quot;FindNode&quot; _
+ , &quot;SetFocus&quot; _
+ , &quot;WriteLine&quot; _
+ )
+
+End Function &apos; SFDialogs.SF_DialogControl.Methods
+
+REM -----------------------------------------------------------------------------
+Public Function Properties() As Variant
+&apos;&apos;&apos; Return the list or properties of the Timer class as an array
+
+ Properties = Array( _
+ &quot;Cancel&quot; _
+ , &quot;Caption&quot; _
+ , &quot;ControlType&quot; _
+ , &quot;CurrentNode&quot; _
+ , &quot;Default&quot; _
+ , &quot;Enabled&quot; _
+ , &quot;Format&quot; _
+ , &quot;ListCount&quot; _
+ , &quot;ListIndex&quot; _
+ , &quot;Locked&quot; _
+ , &quot;MultiSelect&quot; _
+ , &quot;Name&quot; _
+ , &quot;OnActionPerformed&quot; _
+ , &quot;OnAdjustmentValueChanged&quot; _
+ , &quot;OnFocusGained&quot; _
+ , &quot;OnFocusLost&quot; _
+ , &quot;OnItemStateChanged&quot; _
+ , &quot;OnKeyPressed&quot; _
+ , &quot;OnKeyReleased&quot; _
+ , &quot;OnMouseDragged&quot; _
+ , &quot;OnMouseEntered&quot; _
+ , &quot;OnMouseExited&quot; _
+ , &quot;OnMouseMoved&quot; _
+ , &quot;OnMousePressed&quot; _
+ , &quot;OnMouseReleased&quot; _
+ , &quot;OnNodeExpanded&quot; _
+ , &quot;OnNodeSelected&quot; _
+ , &quot;OnTextChanged&quot; _
+ , &quot;Page&quot; _
+ , &quot;Parent&quot; _
+ , &quot;Picture&quot; _
+ , &quot;RootNode&quot; _
+ , &quot;RowSource&quot; _
+ , &quot;Text&quot; _
+ , &quot;TipText&quot; _
+ , &quot;TripleState&quot; _
+ , &quot;Value&quot; _
+ , &quot;Visible&quot; _
+ , &quot;XControlModel&quot; _
+ , &quot;XControlView&quot; _
+ , &quot;XGridColumnModel&quot; _
+ , &quot;XGridDataModel&quot; _
+ , &quot;XTreeDataModel&quot; _
+ )
+
+End Function &apos; SFDialogs.SF_DialogControl.Properties
+
+REM -----------------------------------------------------------------------------
+Public Function SetFocus() As Boolean
+&apos;&apos;&apos; Set the focus on the current Control instance
+&apos;&apos;&apos; Probably called from after an event occurrence
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; True if focusing is successful
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Dim oDlg As Object, oControl As Object
+&apos;&apos;&apos; Set oDlg = CreateScriptService(,, &quot;myControl&quot;) &apos; Control stored in current document&apos;s standard library
+&apos;&apos;&apos; Set oControl = oDlg.Controls(&quot;thisControl&quot;)
+&apos;&apos;&apos; oControl.SetFocus()
+
+Dim bSetFocus As Boolean &apos; Return value
+Const cstThisSub = &quot;SFDialogs.DialogControl.SetFocus&quot;
+Const cstSubArgs = &quot;&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bSetFocus = False
+
+Check:
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not [_Parent]._IsStillAlive() Then GoTo Finally
+ End If
+
+Try:
+ If Not IsNull(_ControlView) Then
+ _ControlView.setFocus()
+ bSetFocus = True
+ End If
+
+Finally:
+ SetFocus = bSetFocus
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFControls.SF_DialogControl.SetFocus
+
+REM -----------------------------------------------------------------------------
+Public Function SetProperty(Optional ByVal PropertyName As Variant _
+ , Optional ByRef Value As Variant _
+ ) As Boolean
+&apos;&apos;&apos; Set a new value to the given property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; PropertyName: the name of the property as a string
+&apos;&apos;&apos; Value: its new value
+&apos;&apos;&apos; Exceptions
+&apos;&apos;&apos; ARGUMENTERROR The property does not exist
+
+Const cstThisSub = &quot;SFDialogs.DialogControl.SetProperty&quot;
+Const cstSubArgs = &quot;PropertyName, Value&quot;
+
+ If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ SetProperty = False
+
+Check:
+ If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
+ End If
+
+Try:
+ SetProperty = _PropertySet(PropertyName, Value)
+
+Finally:
+ SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_DialogControl.SetProperty
+
+REM -----------------------------------------------------------------------------
+Public Function SetTableData(Optional ByRef DataArray As Variant _
+ , Optional ByRef Widths As Variant _
+ , Optional ByRef Alignments As Variant _
+ ) As Boolean
+&apos;&apos;&apos; Fill a table control with the given data. Preexisting data is erased
+&apos;&apos;&apos; The Basic IDE allows to define if the control has a row and/or a column header
+&apos;&apos;&apos; When it is the case, the array in argument should contain those headers resp. in the first
+&apos;&apos;&apos; column and/or in the first row
+&apos;&apos;&apos; A column in the control shall be sortable when the data (headers excluded) in that column
+&apos;&apos;&apos; is homogeneously filled either with numbers or with strings
+&apos;&apos;&apos; Columns containing strings will be left-aligned, those with numbers will be right-aligned
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; DataArray: the set of data to display in the table control, including optional column/row headers
+&apos;&apos;&apos; Is a 2D array in Basic, is a tuple of tuples when called from Python
+&apos;&apos;&apos; Widths: the column&apos;s relative widths as a 1D array, each element corresponding with a column
+&apos;&apos;&apos; If the array is shorter than the number of columns, the last value is kept for the next columns.
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Widths := Array(1, 2)
+&apos;&apos;&apos; means that the first column is half as wide as all the other columns
+&apos;&apos;&apos; When the argument is absent, the columns are evenly spread over the control
+&apos;&apos;&apos; Alignments: the column&apos;s horizontal alignment as a string with length = number of columns.
+&apos;&apos;&apos; Possible characters are:
+&apos;&apos;&apos; L(EFT), C(ENTER), R(IGHT) or space (default behaviour)
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; True when successful
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; Dim myTable As Object, bSet As Boolean, vData As Variant
+&apos;&apos;&apos; Set myTable = myDialog.Controls(&quot;myTableControl&quot;) &apos; This control has only column headers
+&apos;&apos;&apos; vData = Array(&quot;Col1&quot;, &quot;Col2&quot;, &quot;Col3&quot;)
+&apos;&apos;&apos; vData = SF_Array.AppendRow(vData, Array(1, 2, 3))
+&apos;&apos;&apos; vData = SF_Array.AppendRow(vData, Array(4, 5, 6))
+&apos;&apos;&apos; vData = SF_Array.AppendRow(vData, Array(7, 8, 9))
+&apos;&apos;&apos; bSet = myTable.SetTableData(vData, Alignments := &quot; C &quot;)
+
+Dim bData As Boolean &apos; Return value
+Dim iDims As Integer &apos; Number of dimensions of DataArray
+Dim lMin1 As Long &apos; LBound1 of input array
+Dim lMax1 As Long &apos; UBound1 of input array
+Dim lMin2 As Long &apos; LBound2 of input array
+Dim lMax2 As Long &apos; UBound2 of input array
+Dim lControlWidth As Long &apos; Width of the table control
+Dim lMinW As Long &apos; lBound of Widths
+Dim lMaxW As Long &apos; UBound of vWidths
+Dim lMinRow As Long &apos; Row index of effective data subarray
+Dim lMinCol As Long &apos; Column index of effective data subarray
+Dim vRowHeaders As Variant &apos; Array of row headers
+Dim sRowHeader As String &apos; A single row header
+Dim vColHeaders As Variant &apos; Array of column headers
+Dim oColumn As Object &apos; com.sun.star.awt.grid.XGridColumn
+Dim dWidth As Double &apos; A single item of Widths
+Dim dRelativeWidth As Double &apos; Sum of Widths up to the number of columns
+Dim dWidthFactor As Double &apos; Factor to apply to relative widths to get absolute column widths
+Dim vDataRow As Variant &apos; A single row content in the tablecontrol
+Dim vDataItem As Variant &apos; A single DataArray item
+Dim sAlign As String &apos; Column&apos;s horizontal alignments (single chars: L, C, R, space)
+Dim lAlign As Long &apos; com.sun.star.style.HorizontalAlignment.XXX
+Dim i As Long, j As Long, k As Long
+
+Const cstRowHdrWidth = 12 &apos; Estimated width of the row header
+
+Const cstThisSub = &quot;SFDialogs.DialogControl.SetTableData&quot;
+Const cstSubArgs = &quot;DataArray, [Widths=Array(1)], [Alignments=&quot;&quot;&quot;&quot;]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bData = False
+
+Check:
+ If IsMissing(Widths) Or IsEmpty(Widths) Then Widths = Array(1)
+ If IsMissing(Alignments) Or IsEmpty(Alignments) Then Alignments = &quot;&quot;
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If _ControlType &lt;&gt; CTLTABLECONTROL Then GoTo CatchType
+ If Not ScriptForge.SF_Utils._ValidateArray(DataArray, &quot;DataArray&quot;) Then GoTo Catch &apos; Dimensions are checked below
+ If Not ScriptForge.SF_Utils._ValidateArray(Widths, &quot;Widths&quot;, 1, ScriptForge.V_NUMERIC, True) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Alignments, &quot;Alignments&quot;, V_STRING) Then GoTo Catch
+ End If
+
+Try:
+ &apos; Erase any pre-existing data and columns
+ _GridDataModel.removeAllRows()
+ For i = _GridColumnModel.ColumnCount - 1 To 0 Step -1
+ _GridColumnModel.removeColumn(i)
+ Next i
+
+ &apos; LBounds, UBounds - Basic or Pytho
+ iDims = ScriptForge.SF_Array.CountDims(DataArray)
+ Select Case iDims
+ Case -1, 0 : GoTo Catch
+ Case 1 &apos; Called probably from Python
+ lMin1 = LBound(DataArray, 1) : lMax1 = UBound(DataArray, 1)
+ If Not IsArray(DataArray(0)) Then GoTo Catch
+ If UBound(DataArray(0)) &lt; LBound(DataArray(0)) Then GoTo Catch &apos; No columns
+ lMin2 = LBound(DataArray(0)) : lMax2 = UBound(DataArray(0))
+ Case 2
+ lMin1 = LBound(DataArray, 1) : lMax1 = UBound(DataArray, 1)
+ lMin2 = LBound(DataArray, 2) : lMax2 = UBound(DataArray, 2)
+ Case Else : GoTo Catch
+ End Select
+
+ &apos; Extract headers from data array
+ lMinW = LBound(Widths) : lMaxW = UBound(Widths)
+ With _ControlModel
+ If .ShowColumnHeader Then
+ lMinRow = lMin1 + 1
+ If iDims = 1 Then
+ vColHeaders = DataArray(lMin1)
+ Else
+ vColHeaders = ScriptForge.SF_Array.ExtractRow(DataArray, lMin1)
+ End If
+ Else
+ lMinRow = lMin1
+ vColHeaders = Array()
+ End If
+ If .ShowRowHeader Then
+ lMinCol = lMin2 + 1
+ If iDims = 1 Then
+ vRowHeaders = Array()
+ ReDim vRowHeaders(lMin1 To lMax1)
+ For i = lMin1 To lMax1
+ vRowHeaders(i) = DataArray(i)(lMin2)
+ Next i
+ Else
+ vRowHeaders = ScriptForge.SF_Array.ExtractColumn(DataArray, lMin2)
+ End If
+ Else
+ lMinCol = lMin2
+ vRowHeaders = Array()
+ End If
+ End With
+
+ &apos; Create the columns
+ For j = lMinCol To lMax2
+ Set oColumn = _GridColumnModel.createColumn()
+ If _ControlModel.ShowColumnHeader Then oColumn.Title = vColHeaders(j)
+ _GridColumnModel.addColumn(oColumn)
+ Next j
+ &apos; Size the columns. Column sizing cannot be done before all the columns are added
+ If lMaxW &gt;= lMinW Then &apos; There must be at least 1 width given as argument
+ &apos; Size the columns proportionally with their relative widths
+ dRelativeWidth = 0.0
+ i = lMinW - 1
+ &apos; Compute the sum of the relative widths
+ For j = 0 To lMax2 - lMinCol
+ i = i + 1
+ If i &gt;= lMinW And i &lt;= lMaxW Then dRelativeWidth = dRelativeWidth + Widths(i) Else dRelativeWidth = dRelativeWidth + Widths(lMaxW)
+ Next j
+ &apos; Set absolute widths
+ If dRelativeWidth &gt; 0.0 Then dWidthFactor = CDbl((_ControlModel.Width - cstRowHdrWidth) / dRelativeWidth) Else dWidthFactor = 1.0
+ i = lMinW - 1
+ For j = 0 To lMax2 - lMinCol
+ i = i + 1
+ If i &gt;= lMinW And i &lt;= lMaxW Then dWidth = CDbl(Widths(i)) Else dWidth = CDbl(Widths(lMaxW))
+ _GridColumnModel.Columns(j).ColumnWidth = CLng(dWidthFactor * dWidth)
+ Next j
+ Else
+ &apos; Size all columns evenly
+ For j = 0 To lMax2 - lMinCol
+ _GridColumnModel.Columns(j).ColumnWidth = (_ControlModel.Width - cstRowHdrWidth) / (lMax2 - lMonCol + 1)
+ Next j
+ End If
+
+ &apos; Initialize the column alignment
+ If Len(Alignments) &gt;= lMax2 - lMinCol + 1 Then sAlign = Alignments Else sAlign = Alignments &amp; Space(lMax2 - lMinCol + 1 - Len(Alignments))
+
+ &apos; Feed the table with data and define/confirm the column alignment
+ vDataRow = Array()
+ For i = lMinRow To lMax1
+ ReDim vDataRow(0 To lMax2 - lMinCol)
+ For j = lMinCol To lMax2
+ If iDims = 1 Then vDataItem = DataArray(i)(j) Else vDataItem = DataArray(i, j)
+ If VarType(vDataItem) = V_STRING Then
+ ElseIf ScriptForge.SF_Utils._VarTypeExt(vDataItem) = ScriptForge.V_NUMERIC Then
+ Else
+ vDataItem = ScriptForge.SF_String.Represent(vDataItem)
+ End If
+ vDataRow(j - lMinCol) = vDataItem
+ &apos; Store alignment while processing the first row of the array
+ If i = lMinRow Then
+ k = j - lMinCol + 1
+ If Mid(sAlign, k, 1) = &quot; &quot; Then Mid(sAlign, k, 1) = Iif(VarType(vDataItem) = V_STRING, &quot;L&quot;, &quot;R&quot;)
+ End If
+ Next j
+ If _ControlModel.ShowRowHeader Then sRowHeader = vRowHeaders(i) Else sRowHeader = &quot;&quot;
+ _GridDataModel.addRow(sRowHeader, vDataRow)
+ Next i
+
+ &apos; Determine alignments of each column
+ For j = 0 To lMax2 - lMinCol
+ Select Case Mid(sAlign, j + 1, 1)
+ Case &quot;L&quot;, &quot; &quot; : lAlign = com.sun.star.style.HorizontalAlignment.LEFT
+ Case &quot;R&quot; : lAlign = com.sun.star.style.HorizontalAlignment.RIGHT
+ Case &quot;C&quot; : lAlign = com.sun.star.style.HorizontalAlignment.CENTER
+ Case Else
+ End Select
+ _GridColumnModel.Columns(j).HorizontalAlign = lAlign
+ Next j
+
+ bData = True
+
+Finally:
+ SetTableData = bData
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+CatchType:
+ ScriptForge.SF_Exception.RaiseFatal(CONTROLTYPEERROR, _Name, _DialogName, _ControlType, &quot;SetTableData&quot;)
+ GoTo Finally
+End Function &apos; SFDialogs.SF_DialogControl.SetTableData
+
+REM -----------------------------------------------------------------------------
+Public Function WriteLine(Optional ByVal Line As Variant) As Boolean
+&apos;&apos;&apos; Add a new line to a multiline TextField control
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Line: (default = &quot;&quot;) the line to insert at the end of the text box
+&apos;&apos;&apos; a newline character will be inserted before the line, if relevant
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; True if insertion is successful
+&apos;&apos;&apos; Exceptions
+&apos;&apos;&apos; TEXTFIELDERROR Method applicable on multiline text fields only
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Dim oDlg As Object, oControl As Object
+&apos;&apos;&apos; Set oDlg = CreateScriptService(,, &quot;myControl&quot;) &apos; Control stored in current document&apos;s standard library
+&apos;&apos;&apos; Set oControl = oDlg.Controls(&quot;thisControl&quot;)
+&apos;&apos;&apos; oControl.WriteLine(&quot;a new line&quot;)
+
+Dim bWriteLine As Boolean &apos; Return value
+Dim lTextLength As Long &apos; Actual length of text in box
+Dim oSelection As New com.sun.star.awt.Selection
+Dim sNewLine As String &apos; Newline character(s)
+Const cstThisSub = &quot;SFDialogs.DialogControl.WriteLine&quot;
+Const cstSubArgs = &quot;[Line=&quot;&quot;&quot;&quot;]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bWriteLine = False
+
+Check:
+ If IsMissing(Line) Or IsEmpty(Line) Then Line = &quot;&quot;
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not [_Parent]._IsStillAlive() Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(Line, &quot;Line&quot;, V_STRING) Then GoTo Finally
+ End If
+ If ControlType &lt;&gt; CTLTEXTFIELD Then GoTo CatchField
+ If _ControlModel.MultiLine = False Then GoTo CatchField
+
+Try:
+ _ControlModel.HardLineBreaks = True
+ sNewLine = ScriptForge.SF_String.sfNEWLINE
+ With _ControlView
+ lTextLength = Len(.getText())
+ If lTextLength = 0 Then &apos; Text field is still empty
+ oSelection.Min = 0 : oSelection.Max = 0
+ .setText(Line)
+ Else &apos; Put cursor at the end of the actual text
+ oSelection.Min = lTextLength : oSelection.Max = lTextLength
+ .insertText(oSelection, sNewLine &amp; Line)
+ End If
+ &apos; Put the cursor at the end of the inserted text
+ oSelection.Max = oSelection.Max + Len(sNewLine) + Len(Line)
+ oSelection.Min = oSelection.Max
+ .setSelection(oSelection)
+ End With
+ bWriteLine = True
+
+Finally:
+ WriteLine = bWriteLine
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+CatchField:
+ ScriptForge.SF_Exception.RaiseFatal(TEXTFIELDERROR, _Name, _DialogName)
+ GoTo Finally
+End Function &apos; SFControls.SF_DialogControl.WriteLine
+
+REM =========================================================== PRIVATE FUNCTIONS
+
+REM -----------------------------------------------------------------------------
+Private Function _FindNode(ByRef poNode As Object _
+ , ByVal psDisplayValue As String _
+ , ByRef pvDataValue As Variant _
+ , ByVal pbCaseSensitive As Boolean _
+ ) As Object
+&apos;&apos;&apos; Traverses the tree and find recursively, starting from the root, a node meeting some criteria
+&apos;&apos;&apos; Either (1 match is enough):
+&apos;&apos;&apos; having its DisplayValue like psDisplayValue
+&apos;&apos;&apos; having its DataValue = pvDataValue
+&apos;&apos;&apos; Comparisons may be or not case-sensitive
+&apos;&apos;&apos; The first matching occurrence is returned
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; poNode: the current node, the root at 1st call
+&apos;&apos;&apos; psDisplayValue: the pattern to be matched
+&apos;&apos;&apos; pvDataValue: a string, a numeric value or a date or Empty (if not applicable)
+&apos;&apos;&apos; pbCaseSensitive: applicable on both criteria
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The found node of type com.sun.star.awt.tree.XMutableTreeNode
+
+Dim oChild As Object &apos; Child node com.sun.star.awt.tree.XMutableTreeNode
+Dim oFind As Object &apos; Found node com.sun.star.awt.tree.XMutableTreeNode
+Dim lChildCount As Long &apos; Number of children of a node
+Dim bFound As Boolean &apos; True when node found
+Dim i As Long
+
+ Set _FindNode = Nothing
+ On Local Error GoTo Finally &apos; Better not found than raise an error
+
+Check:
+ &apos; Does the actual node match the criteria ?
+ bFound = False
+ If Len(psDisplayValue) &gt; 0 Then
+ bFound = ScriptForge.SF_String.IsLike(poNode.DisplayValue, psDisplayValue, pbCaseSensitive)
+ End If
+ If Not bFound And Not IsEmpty(poNode.DataValue) Then
+ If Not IsEmpty(pvdataValue) Then bFound = ( ScriptForge.SF_Array._ValCompare(poNode.DataValue, pvDataB-Value, pbCaseSensitive) = 0 )
+ End If
+ If bFound Then
+ Set _FindNode = poNode
+ Exit Function
+ End If
+
+Try:
+ &apos; Explore sub-branches
+ lChildCount = poNode.getChildCount
+ If lChildCount &gt; 0 Then
+ For i = 0 To lChildCount - 1
+ Set oChild = poNode.getChildAt(i)
+ Set oFind = _FindNode(oChild, psDisplayValue, pvDataValue, pbCaseSensitive) &apos; Recursive call
+ If Not IsNull(oFind) Then
+ Set _FindNode = oFind
+ Exit For
+ End If
+ Next i
+ End If
+
+Finally:
+ Exit Function
+End Function &apos; SFDialogs.SF_DialogControl._FindNode
+
+REM -----------------------------------------------------------------------------
+Private Function _FormatsList() As Variant
+&apos;&apos;&apos; Return the allowed format entries as a zero-based array for Date and Time control types
+
+Dim vFormats() As Variant &apos; Return value
+
+ Select Case _ControlType
+ Case CTLDATEFIELD
+ vFormats = Array( _
+ &quot;Standard (short)&quot; _
+ , &quot;Standard (short YY)&quot; _
+ , &quot;Standard (short YYYY)&quot; _
+ , &quot;Standard (long)&quot; _
+ , &quot;DD/MM/YY&quot; _
+ , &quot;MM/DD/YY&quot; _
+ , &quot;YY/MM/DD&quot; _
+ , &quot;DD/MM/YYYY&quot; _
+ , &quot;MM/DD/YYYY&quot; _
+ , &quot;YYYY/MM/DD&quot; _
+ , &quot;YY-MM-DD&quot; _
+ , &quot;YYYY-MM-DD&quot; _
+ )
+ Case CTLTIMEFIELD
+ vFormats = Array( _
+ &quot;24h short&quot; _
+ , &quot;24h long&quot; _
+ , &quot;12h short&quot; _
+ , &quot;12h long&quot; _
+ )
+ Case Else
+ vFormats = Array()
+ End Select
+
+ _FormatsList = vFormats
+
+End Function &apos; SFDialogs.SF_DialogControl._FormatsList
+
+REM -----------------------------------------------------------------------------
+Public Function _GetEventName(ByVal psProperty As String) As String
+&apos;&apos;&apos; Return the LO internal event name derived from the SF property name
+&apos;&apos;&apos; The SF property name is not case sensitive, while the LO name is case-sensitive
+&apos; Corrects the typo on ErrorOccur(r?)ed, if necessary
+
+Dim vProperties As Variant &apos; Array of class properties
+Dim sProperty As String &apos; Correctly cased property name
+
+ vProperties = Properties()
+ sProperty = vProperties(ScriptForge.SF_Array.IndexOf(vProperties, psProperty, SortOrder := &quot;ASC&quot;))
+
+ _GetEventName = LCase(Mid(sProperty, 3, 1)) &amp; Right(sProperty, Len(sProperty) - 3)
+
+End Function &apos; SFDialogs.SF_DialogControl._GetEventName
+
+REM -----------------------------------------------------------------------------
+Private Function _GetListener(ByVal psEventName As String) As String
+&apos;&apos;&apos; Getting/Setting macros triggered by events requires a Listener-EventName pair
+&apos;&apos;&apos; Return the X...Listener corresponding with the event name in argument
+
+ Select Case UCase(psEventName)
+ Case UCase(&quot;OnActionPerformed&quot;)
+ _GetListener = &quot;XActionListener&quot;
+ Case UCase(&quot;OnAdjustmentValueChanged&quot;)
+ _GetListener = &quot;XAdjustmentListener&quot;
+ Case UCase(&quot;OnFocusGained&quot;), UCase(&quot;OnFocusLost&quot;)
+ _GetListener = &quot;XFocusListener&quot;
+ Case UCase(&quot;OnItemStateChanged&quot;)
+ _GetListener = &quot;XItemListener&quot;
+ Case UCase(&quot;OnKeyPressed&quot;), UCase(&quot;OnKeyReleased&quot;)
+ _GetListener = &quot;XKeyListener&quot;
+ Case UCase(&quot;OnMouseDragged&quot;), UCase(&quot;OnMouseMoved&quot;)
+ _GetListener = &quot;XMouseMotionListener&quot;
+ Case UCase(&quot;OnMouseEntered&quot;), UCase(&quot;OnMouseExited&quot;), UCase(&quot;OnMousePressed&quot;), UCase(&quot;OnMouseReleased&quot;)
+ _GetListener = &quot;XMouseListener&quot;
+ Case UCase(&quot;OnTextChanged&quot;)
+ _GetListener = &quot;XTextListener&quot;
+ Case Else
+ _GetListener = &quot;&quot;
+ End Select
+
+End Function &apos; SFDialogs.SF_DialogControl._GetListener
+
+REM -----------------------------------------------------------------------------
+Public Sub _Initialize()
+&apos;&apos;&apos; Complete the object creation process:
+&apos;&apos;&apos; - Initialization of private members
+&apos;&apos;&apos; - Collection of specific attributes
+&apos;&apos;&apos; - synchronization with parent dialog instance
+
+Dim vServiceName As Variant &apos; Split service name
+Dim sType As String &apos; Last component of service name
+
+Try:
+ _ImplementationName = _ControlModel.getImplementationName()
+
+ &apos; Identify the control type
+ vServiceName = Split(_ControlModel.getServiceName(), &quot;.&quot;)
+ sType = vServiceName(UBound(vServiceName))
+ Select Case 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 = CreateUnoService(&quot;com.sun.star.awt.tree.MutableTreeDataModel&quot;)
+ Set _TreeDataModel = _ControlModel.DataModel
+ Case &quot;UnoControlGridModel&quot;
+ _ControlType = CTLTABLECONTROL
+ Set _GridColumnModel = _ControlModel.ColumnModel
+ Set _GridDataModel = _ControlModel.GridDataModel
+ Case Else : _ControlType = sType
+ End Select
+
+ &apos; Store the SF_DialogControl object in the parent cache
+ Set _Parent._ControlCache(_IndexOfNames) = [Me]
+
+Finally:
+ Exit Sub
+End Sub &apos; SFDialogs.SF_DialogControl._Initialize
+
+REM -----------------------------------------------------------------------------
+Private Function _PropertyGet(Optional ByVal psProperty As String _
+ , Optional ByVal pvDefault As Variant _
+ ) As Variant
+&apos;&apos;&apos; Return the value of the named property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psProperty: the name of the property
+&apos;&apos;&apos; pvDefault: the value returned when the property is not applicable on the control&apos;s type
+&apos;&apos;&apos; Getting a non-existing property for a specific control type should
+&apos;&apos;&apos; not generate an error to not disrupt the Basic IDE debugger
+
+Dim vGet As Variant &apos; Return value
+Static oSession As Object &apos; Alias of SF_Session
+Dim vSelection As Variant &apos; Alias of Model.SelectedItems or Model.Selection
+Dim vList As Variant &apos; Alias of Model.StringItemList
+Dim lIndex As Long &apos; Index in StringItemList
+Dim sItem As String &apos; A single item
+Dim vDate As Variant &apos; com.sun.star.util.Date or com.sun.star.util.Time
+Dim vValues As Variant &apos; Array of listbox values
+Dim oControlEvents As Object &apos; com.sun.star.container.XNameContainer
+Dim sEventName As String &apos; Internal event name
+Dim i As Long
+Dim cstThisSub As String
+Const cstSubArgs = &quot;&quot;
+
+ cstThisSub = &quot;SFDialogs.DialogControl.get&quot; &amp; psProperty
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+ ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+ If Not [_Parent]._IsStillAlive() Then GoTo Finally
+
+ If IsMissing(pvDefault) Then pvDefault = Null
+ _PropertyGet = pvDefault
+
+ If IsNull(oSession) Then Set oSession = ScriptForge.SF_Services.CreateScriptService(&quot;Session&quot;)
+ Select Case UCase(psProperty)
+ Case UCase(&quot;Cancel&quot;)
+ Select Case _ControlType
+ Case CTLBUTTON
+ If oSession.HasUNOProperty(_ControlModel, &quot;PushButtonType&quot;) Then _PropertyGet = ( _ControlModel.PushButtonType = com.sun.star.awt.PushButtonType.CANCEL )
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Caption&quot;)
+ Select Case _ControlType
+ Case CTLBUTTON, CTLCHECKBOX, CTLFIXEDLINE, CTLFIXEDTEXT, CTLGROUPBOX, CTLRADIOBUTTON
+ If oSession.HasUNOProperty(_ControlModel, &quot;Label&quot;) Then _PropertyGet = _ControlModel.Label
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;ControlType&quot;)
+ _PropertyGet = _ControlType
+ Case UCase(&quot;CurrentNode&quot;)
+ Select Case _ControlType
+ Case CTLTREECONTROL
+ If oSession.HasUNOMethod(_ControlView, &quot;getSelection&quot;) Then
+ _PropertyGet = Empty
+ If _ControlModel.SelectionType &lt;&gt; com.sun.star.view.SelectionType.NONE Then
+ vSelection = _ControlView.getSelection()
+ If IsArray(vSelection) Then
+ If UBound(vSelection) &gt;= 0 Then Set _PropertyGet = vSelection(0)
+ Else
+ Set _PropertyGet = vSelection
+ End If
+ End If
+ End If
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Default&quot;)
+ Select Case _ControlType
+ Case CTLBUTTON
+ If oSession.HasUNOProperty(_ControlModel, &quot;DefaultButton&quot;) Then _PropertyGet = _ControlModel.DefaultButton
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Enabled&quot;)
+ If oSession.HasUnoProperty(_ControlModel, &quot;Enabled&quot;) Then _PropertyGet = _ControlModel.Enabled
+ Case UCase(&quot;Format&quot;)
+ Select Case _ControlType
+ Case CTLDATEFIELD
+ If oSession.HasUNOProperty(_ControlModel, &quot;DateFormat&quot;) Then _PropertyGet = _FormatsList()(_ControlModel.DateFormat)
+ Case CTLTIMEFIELD
+ If oSession.HasUNOProperty(_ControlModel, &quot;TimeFormat&quot;) Then _PropertyGet = _FormatsList()(_ControlModel.TimeFormat)
+ Case CTLFORMATTEDFIELD
+ If oSession.HasUNOProperty(_ControlModel, &quot;FormatsSupplier&quot;) And oSession.HasUNOProperty(_ControlModel, &quot;FormatKey&quot;) Then
+ _PropertyGet = _ControlModel.FormatsSupplier.getNumberFormats.getByKey(_ControlModel.FormatKey).FormatString
+ End If
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;ListCount&quot;)
+ Select Case _ControlType
+ Case CTLCOMBOBOX, CTLLISTBOX
+ If oSession.HasUNOProperty(_ControlModel, &quot;StringItemList&quot;) Then _PropertyGet = UBound(_ControlModel.StringItemList) + 1
+ Case CTLTABLECONTROL &apos; Returns zero when no table data yet
+ If oSession.HasUNOProperty(_GridDataModel, &quot;RowCount&quot;) Then _PropertyGet = _GridDataModel.RowCount
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;ListIndex&quot;)
+ Select Case _ControlType
+ Case CTLCOMBOBOX
+ _PropertyGet = -1 &apos; Not found, multiselection
+ If oSession.HasUNOProperty(_ControlModel, &quot;Text&quot;) And oSession.HasUNOProperty(_ControlModel, &quot;StringItemList&quot;) Then
+ _PropertyGet = ScriptForge.SF_Array.IndexOf(_ControlModel.StringItemList, _ControlModel.Text, CaseSensitive := True)
+ End If
+ Case CTLLISTBOX
+ _PropertyGet = -1 &apos; Not found, multiselection
+ If oSession.HasUNOProperty(_ControlModel, &quot;SelectedItems&quot;) And oSession.HasUNOProperty(_ControlModel, &quot;StringItemList&quot;) Then
+ vSelection = _ControlModel.SelectedItems
+ If UBound(vSelection) &gt;= 0 Then _PropertyGet = vSelection(0)
+ End If
+ Case CTLTABLECONTROL
+ _PropertyGet = -1 &apos; No row selected, no data, multiselection
+ If oSession.HasUNOProperty(_ControlModel, &quot;SelectionModel&quot;) _
+ And oSession.HasUNOProperty(_ControlView, &quot;CurrentRow&quot;) Then
+ &apos; Other selection types (multi, range) not supported
+ If _ControlModel.SelectionModel = com.sun.star.view.SelectionType.SINGLE Then
+ lIndex = _ControlView.CurrentRow
+ If lIndex &lt; 0 And oSession.HasUNOProperty(_ControlView, &quot;SelectedRows&quot;) Then
+ If UBound(_ControlView.SelectedRows) &gt;= 0 Then lIndex = _ControlView.SelectedRows(0)
+ End If
+ _PropertyGet = lIndex
+ End If
+ End If
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Locked&quot;)
+ Select Case _ControlType
+ Case CTLCOMBOBOX, CTLCURRENCYFIELD, CTLDATEFIELD, CTLFILECONTROL, CTLFORMATTEDFIELD, CTLLISTBOX _
+ , CTLNUMERICFIELD, CTLPATTERNFIELD, CTLTEXTFIELD, CTLTIMEFIELD
+ If oSession.HasUnoProperty(_ControlModel, &quot;ReadOnly&quot;) Then _PropertyGet = _ControlModel.ReadOnly
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;MultiSelect&quot;)
+ Select Case _ControlType
+ Case CTLLISTBOX
+ If oSession.HasUnoProperty(_ControlModel, &quot;MultiSelection&quot;) Then
+ _PropertyGet = _ControlModel.MultiSelection
+ ElseIf oSession.HasUnoProperty(_ControlModel, &quot;MultiSelectionSimpleMode&quot;) Then &apos; Not documented: gridcontrols only TBC ??
+ _PropertyGet = _ControlModel.MultiSelectionSimpleMode
+ End If
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Name&quot;)
+ _PropertyGet = _Name
+ Case UCase(&quot;OnActionPerformed&quot;), UCase(&quot;OnAdjustmentValueChanged&quot;), UCase(&quot;OnFocusGained&quot;), UCase(&quot;OnFocusLost&quot;) _
+ , UCase(&quot;OnItemStateChanged&quot;), UCase(&quot;OnKeyPressed&quot;), UCase(&quot;OnKeyReleased&quot;) _
+ , UCase(&quot;OnMouseDragged&quot;), UCase(&quot;OnMouseEntered&quot;), UCase(&quot;OnMouseExited&quot;), UCase(&quot;OnMouseMoved&quot;) _
+ , UCase(&quot;OnMousePressed&quot;), UCase(&quot;OnMouseReleased&quot;), UCase(&quot;OnTextChanged&quot;)
+ Set oControlEvents = _ControlModel.getEvents()
+ sEventName = &quot;com.sun.star.awt.&quot; &amp; _GetListener(psProperty) &amp; &quot;::&quot; &amp; _GetEventName(psProperty)
+ If oControlEvents.hasByName(sEventName) Then
+ _PropertyGet = oControlEvents.getByName(sEventName).ScriptCode
+ Else
+ _PropertyGet = &quot;&quot;
+ End If
+ Case UCase(&quot;OnNodeExpanded&quot;)
+ Select Case _ControlType
+ Case CTLTREECONTROL
+ _PropertyGet = _OnNodeExpanded
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;OnNodeSelected&quot;)
+ Select Case _ControlType
+ Case CTLTREECONTROL
+ _PropertyGet = _OnNodeSelected
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Page&quot;)
+ If oSession.HasUnoProperty(_ControlModel, &quot;Step&quot;) Then _PropertyGet = _ControlModel.Step
+ Case UCase(&quot;Parent&quot;)
+ Set _PropertyGet = [_Parent]
+ Case UCase(&quot;Picture&quot;)
+ Select Case _ControlType
+ Case CTLBUTTON, CTLIMAGECONTROL
+ If oSession.HasUnoProperty(_ControlModel, &quot;ImageURL&quot;) Then _PropertyGet = ScriptForge.SF_FileSystem._ConvertFromUrl(_ControlModel.ImageURL)
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;RootNode&quot;)
+ Select Case _ControlType
+ Case CTLTREECONTROL
+ _PropertyGet = _TreeDataModel.getRoot()
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;RowSource&quot;)
+ Select Case _ControlType
+ Case CTLCOMBOBOX, CTLLISTBOX
+ If oSession.HasUnoProperty(_ControlModel, &quot;StringItemList&quot;) Then
+ If IsArray(_ControlModel.StringItemList) Then _PropertyGet = _ControlModel.StringItemList Else _PropertyGet = Array(_ControlModel.StringItemList)
+ End If
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Text&quot;)
+ Select Case _ControlType
+ Case CTLCOMBOBOX, CTLFILECONTROL, CTLFORMATTEDFIELD, CTLPATTERNFIELD, CTLTEXTFIELD
+ If oSession.HasUnoProperty(_ControlModel, &quot;Text&quot;) Then _PropertyGet = _ControlModel.Text
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;TipText&quot;)
+ If oSession.HasUnoProperty(_ControlModel, &quot;HelpText&quot;) Then _PropertyGet = _ControlModel.HelpText
+ Case UCase(&quot;TripleState&quot;)
+ Select Case _ControlType
+ Case CTLCHECKBOX
+ If oSession.HasUnoProperty(_ControlModel, &quot;TriState&quot;) Then _PropertyGet = _ControlModel.TriState
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Value&quot;) &apos; Default values are set here by control type, not in the 2nd argument
+ vGet = pvDefault
+ Select Case _ControlType
+ Case CTLBUTTON &apos;Boolean, toggle buttons only
+ vGet = False
+ If oSession.HasUnoProperty(_ControlModel, &quot;Toggle&quot;) Then
+ If oSession.HasUnoProperty(_ControlModel, &quot;State&quot;) Then vGet = ( _ControlModel.State = 1 )
+ End If
+ Case CTLCHECKBOX &apos;0 = Not checked, 1 = Checked, 2 = Don&apos;t know
+ If oSession.HasUnoProperty(_ControlModel, &quot;State&quot;) Then vGet = _ControlModel.State Else vGet = 2
+ Case CTLCOMBOBOX, CTLFILECONTROL, CTLPATTERNFIELD, CTLTEXTFIELD &apos;String
+ If oSession.HasUnoProperty(_ControlModel, &quot;Text&quot;) Then vGet = _ControlModel.Text Else vGet = &quot;&quot;
+ Case CTLCURRENCYFIELD, CTLNUMERICFIELD &apos;Numeric
+ If oSession.HasUnoProperty(_ControlModel, &quot;Value&quot;) Then vGet = _ControlModel.Value Else vGet = 0
+ Case CTLDATEFIELD &apos;Date
+ vGet = CDate(1)
+ If oSession.HasUnoProperty(_ControlModel, &quot;Date&quot;) Then
+ If VarType(_ControlModel.Date) = ScriptForge.V_OBJECT Then &apos; com.sun.star.util.Date
+ Set vDate = _ControlModel.Date
+ vGet = DateSerial(vDate.Year, vDate.Month, vDate.Day)
+ End If
+ End If
+ Case CTLFORMATTEDFIELD &apos;String or numeric
+ If oSession.HasUnoProperty(_ControlModel, &quot;EffectiveValue&quot;) Then vGet = _ControlModel.EffectiveValue Else vGet = &quot;&quot;
+ Case CTLLISTBOX &apos;String or array of strings depending on MultiSelection
+ &apos; StringItemList is the list of the items displayed in the box
+ &apos; SelectedItems is the list of the indexes in StringItemList of the selected items
+ &apos; It can go beyond the limits of StringItemList
+ &apos; It can contain multiple values even if the listbox is not multiselect
+ If oSession.HasUnoProperty(_ControlModel, &quot;StringItemList&quot;) And oSession.HasUnoProperty(_ControlModel, &quot;SelectedItems&quot;) _
+ And oSession.HasUnoProperty(_ControlModel, &quot;MultiSelection&quot;) Then
+ vSelection = _ControlModel.SelectedItems
+ vList = _ControlModel.StringItemList
+ If _ControlModel.MultiSelection Then vValues = Array()
+ For i = 0 To UBound(vSelection)
+ lIndex = vSelection(i)
+ If lIndex &gt;= 0 And lIndex &lt;= UBound(vList) Then
+ If Not _ControlModel.MultiSelection Then
+ vValues = vList(lIndex)
+ Exit For
+ End If
+ vValues = ScriptForge.SF_Array.Append(vValues, vList(lIndex))
+ End If
+ Next i
+ vGet = vValues
+ Else
+ vGet = &quot;&quot;
+ End If
+ Case CTLPROGRESSBAR &apos;Numeric
+ If oSession.HasUnoProperty(_ControlModel, &quot;ProgressValue&quot;) Then vGet = _ControlModel.ProgressValue Else vGet = 0
+ Case CTLRADIOBUTTON &apos;Boolean
+ If oSession.HasUnoProperty(_ControlModel, &quot;State&quot;) Then vGet = ( _ControlModel.State = 1 ) Else vGet = False
+ Case CTLSCROLLBAR &apos;Numeric
+ If oSession.HasUnoProperty(_ControlModel, &quot;ScrollValue&quot;) Then vGet = _ControlModel.ScrollValue Else vGet = 0
+ Case CTLTABLECONTROL
+ vGet = Array() &apos; Default value when no row selected, no data, multiselection
+ If oSession.HasUNOProperty(_ControlModel, &quot;SelectionModel&quot;) _
+ And oSession.HasUNOProperty(_ControlView, &quot;CurrentRow&quot;) Then
+ &apos; Other selection types (multi, range) not supported
+ If _ControlModel.SelectionModel = com.sun.star.view.SelectionType.SINGLE Then
+ lIndex = _ControlView.CurrentRow
+ If lIndex &lt; 0 And oSession.HasUNOProperty(_ControlView, &quot;SelectedRows&quot;) Then
+ If UBound(_ControlView.SelectedRows) &gt;= 0 Then lIndex = _ControlView.SelectedRows(0)
+ End If
+ If lIndex &gt;= 0 Then vGet = _GridDataModel.getRowData(lIndex)
+ End If
+ End If
+ Case CTLTIMEFIELD
+ vGet = CDate(0)
+ If oSession.HasUnoProperty(_ControlModel, &quot;Time&quot;) Then
+ If VarType(_ControlModel.Time) = ScriptForge.V_OBJECT Then &apos; com.sun.star.Util.Time
+ Set vDate = _ControlModel.Time
+ vGet = TimeSerial(vDate.Hours, vDate.Minutes, vDate.Seconds)
+ End If
+ End If
+ Case Else : GoTo CatchType
+ End Select
+ _PropertyGet = vGet
+ Case UCase(&quot;Visible&quot;)
+ If oSession.HasUnoMethod(_ControlView, &quot;isVisible&quot;) Then _PropertyGet = CBool(_ControlView.isVisible())
+ Case UCase(&quot;XControlModel&quot;)
+ Set _PropertyGet = _ControlModel
+ Case UCase(&quot;XControlView&quot;)
+ Set _PropertyGet = _ControlView
+ Case UCase(&quot;XGridColumnModel&quot;)
+ Set _PropertyGet = _GridColumnModel
+ Case UCase(&quot;XGridDataModel&quot;)
+ Set _PropertyGet = _GridDataModel
+ Case UCase(&quot;XTreeDataModel&quot;)
+ Set _PropertyGet = _TreeDataModel
+ Case Else
+ _PropertyGet = Null
+ End Select
+
+Finally:
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+CatchType:
+ GoTo Finally
+End Function &apos; SFDialogs.SF_DialogControl._PropertyGet
+
+REM -----------------------------------------------------------------------------
+Private Function _PropertySet(Optional ByVal psProperty As String _
+ , Optional ByVal pvValue As Variant _
+ ) As Boolean
+&apos;&apos;&apos; Set the new value of the named property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psProperty: the name of the property
+&apos;&apos;&apos; pvValue: the new value of the given property
+
+Dim bSet As Boolean &apos; Return value
+Static oSession As Object &apos; Alias of SF_Session
+Dim vSet As Variant &apos; Value to set in UNO model or view property
+Dim vFormats As Variant &apos; Format property: output of _FormatsList()
+Dim iFormat As Integer &apos; Format property: index in vFormats
+Dim vSelection As Variant &apos; Alias of Model.SelectedItems
+Dim vList As Variant &apos; Alias of Model.StringItemList
+Dim lIndex As Long &apos; Index in StringItemList
+Dim sItem As String &apos; A single item
+Dim vCtlTypes As Variant &apos; Array of allowed control types
+Dim i As Long
+Dim cstThisSub As String
+Const cstSubArgs = &quot;Value&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bSet = False
+
+ cstThisSub = &quot;SFDialogs.DialogControl.set&quot; &amp; psProperty
+ ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+ If Not [_Parent]._IsStillAlive() Then GoTo Finally
+
+ If IsNull(oSession) Then Set oSession = ScriptForge.SF_Services.CreateScriptService(&quot;Session&quot;)
+ bSet = True
+ Select Case UCase(psProperty)
+ Case UCase(&quot;Cancel&quot;)
+ Select Case _ControlType
+ Case CTLBUTTON
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Cancel&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+ If oSession.HasUNOProperty(_ControlModel, &quot;PushButtonType&quot;) Then
+ If pvValue Then vSet = com.sun.star.awt.PushButtonType.CANCEL Else vSet = com.sun.star.awt.PushButtonType.STANDARD
+ _ControlModel.PushButtonType = vSet
+ End If
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Caption&quot;)
+ Select Case _ControlType
+ Case CTLBUTTON, CTLCHECKBOX, CTLFIXEDLINE, CTLFIXEDTEXT, CTLGROUPBOX, CTLRADIOBUTTON
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Caption&quot;, V_STRING) Then GoTo Finally
+ If oSession.HasUNOProperty(_ControlModel, &quot;Label&quot;) Then _ControlModel.Label = pvValue
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;CurrentNode&quot;)
+ Select Case _ControlType
+ Case CTLTREECONTROL
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Selection&quot;, ScriptForge.V_OBJECT) Then GoTo Finally
+ If oSession.UnoObjectType(pvValue) &lt;&gt; &quot;toolkit.MutableTreeNode&quot; Then GoTo CatchType
+ With _ControlView
+ .clearSelection()
+ If Not IsNull(pvValue) Then
+ .addSelection(pvValue)
+ &apos; Suspending temporarily the expansion listener avoids conflicts
+ If Len(_OnNodeExpanded) &gt; 0 Then _ControlView.removeTreeExpansionListener(_ExpandListener)
+ .makeNodeVisible(pvValue) &apos; Expand parent nodes and put node in the display area
+ If Len(_OnNodeExpanded) &gt; 0 Then _ControlView.addTreeExpansionListener(_ExpandListener)
+ End If
+ End With
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Default&quot;)
+ Select Case _ControlType
+ Case CTLBUTTON
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Default&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+ If oSession.HasUNOProperty(_ControlModel, &quot;DefaultButton&quot;) Then _ControlModel.DefaultButton = pvValue
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Enabled&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Enabled&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;Enabled&quot;) Then _ControlModel.Enabled = pvValue
+ Case UCase(&quot;Format&quot;)
+ Select Case _ControlType
+ Case CTLDATEFIELD, CTLTIMEFIELD
+ vFormats = _FormatsList()
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Format&quot;, V_STRING, vFormats) Then GoTo Finally
+ iFormat = ScriptForge.SF_Array.IndexOf(vFormats, pvValue, CaseSensitive := False)
+ If oSession.HasUNOProperty(_ControlModel, &quot;DateFormat&quot;) Then
+ _ControlModel.DateFormat = iFormat
+ ElseIf oSession.HasUNOProperty(_ControlModel, &quot;TimeFormat&quot;) Then
+ _ControlModel.TimeFormat = iFormat
+ End If
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;ListIndex&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;ListIndex&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ Select Case _ControlType
+ Case CTLCOMBOBOX
+ If oSession.HasUNOProperty(_ControlModel, &quot;Text&quot;) And oSession.HasUNOProperty(_ControlModel, &quot;StringItemList&quot;) Then
+ _ControlModel.Text = _ControlModel.StringItemList(CInt(pvValue))
+ End If
+ Case CTLLISTBOX
+ If oSession.HasUNOProperty(_ControlModel, &quot;SelectedItems&quot;) Then _ControlModel.SelectedItems = Array(CInt(pvValue))
+ Case CTLTABLECONTROL
+ If oSession.HasUNOProperty(_ControlModel, &quot;SelectionModel&quot;) _
+ And oSession.HasUNOMethod(_ControlView, &quot;selectRow&quot;) Then
+ &apos; Other selection types (multi, range) not supported
+ If _ControlModel.SelectionModel = com.sun.star.view.SelectionType.SINGLE _
+ And pvValue &gt;= 0 And pvValue &lt;= _GridDataModel.RowCount - 1 Then
+ _ControlView.selectRow(pvValue)
+ End If
+ End If
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Locked&quot;)
+ Select Case _ControlType
+ Case CTLCOMBOBOX, CTLCURRENCYFIELD, CTLDATEFIELD, CTLFILECONTROL, CTLFORMATTEDFIELD, CTLLISTBOX _
+ , CTLNUMERICFIELD, CTLPATTERNFIELD, CTLTEXTFIELD, CTLTIMEFIELD
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Locked&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;ReadOnly&quot;) Then _ControlModel.ReadOnly = pvValue
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;MultiSelect&quot;)
+ Select Case _ControlType
+ Case CTLLISTBOX
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;MultiSelect&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;MultiSelection&quot;) Then _ControlModel.MultiSelection = pvValue
+ If oSession.HasUnoProperty(_ControlModel, &quot;MultiSelectionSimpleMode&quot;) Then _ControlModel.MultiSelectionSimpleMode = pvValue
+ If oSession.HasUnoProperty(_ControlModel, &quot;SelectedItems&quot;) Then
+ If Not pvValue And UBound(_ControlModel.SelectedItems) &gt; 0 Then &apos; Cancel selections when MultiSelect becomes False
+ lIndex = _ControlModel.SelectedItems(0)
+ _ControlModel.SelectedItems = Array(lIndex)
+ End If
+ End If
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;OnNodeExpanded&quot;)
+ Select Case _ControlType
+ Case CTLTREECONTROL
+ If Not ScriptForge.SF_Utils._Validate(pvValue, psProperty, V_STRING) Then GoTo Finally
+ &apos; If the listener was already set, then stop it
+ If Len(_OnNodeExpanded) &gt; 0 Then
+ _ControlView.removeTreeExpansionListener(_ExpandListener)
+ Set _ExpandListener = Nothing
+ _OnNodeExpanded = &quot;&quot;
+ End If
+ &apos; Setup a new fresh listener
+ If Len(pvValue) &gt; 0 Then
+ Set _ExpandListener = CreateUnoListener(&quot;_SFEXP_&quot;, &quot;com.sun.star.awt.tree.XTreeExpansionListener&quot;)
+ _ControlView.addTreeExpansionListener(_ExpandListener)
+ _OnNodeExpanded = pvValue
+ End If
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;OnNodeSelected&quot;)
+ Select Case _ControlType
+ Case CTLTREECONTROL
+ If Not ScriptForge.SF_Utils._Validate(pvValue, psProperty, V_STRING) Then GoTo Finally
+ &apos; If the listener was already set, then stop it
+ If Len(_OnNodeSelected) &gt; 0 Then
+ _ControlView.removeSelectionChangeListener(_SelectListener)
+ Set _SelectListener = Nothing
+ _OnNodeSelected = &quot;&quot;
+ End If
+ &apos; Setup a new fresh listener
+ If Len(pvValue) &gt; 0 Then
+ Set _SelectListener = CreateUnoListener(&quot;_SFSEL_&quot;, &quot;com.sun.star.view.XSelectionChangeListener&quot;)
+ _ControlView.addSelectionChangeListener(_SelectListener)
+ _OnNodeSelected = pvValue
+ End If
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Page&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Page&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;Step&quot;) Then _ControlModel.Step = CLng(pvValue)
+ Case UCase(&quot;Picture&quot;)
+ Select Case _ControlType
+ Case CTLBUTTON, CTLIMAGECONTROL
+ If Not ScriptForge.SF_Utils._ValidateFile(pvValue, &quot;Picture&quot;) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;ImageURL&quot;) Then _ControlModel.ImageURL = ScriptForge.SF_FileSystem._ConvertToUrl(pvValue)
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;RowSource&quot;)
+ Select Case _ControlType
+ Case CTLCOMBOBOX, CTLLISTBOX
+ If Not IsArray(pvValue) Then
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;RowSource&quot;, V_STRING) Then GoTo Finally
+ pvArray = Array(pvArray)
+ ElseIf Not ScriptForge.SF_Utils._ValidateArray(pvValue, &quot;RowSource&quot;, 1, V_STRING, True) Then
+ GoTo Finally
+ End If
+ If oSession.HasUnoProperty(_ControlModel, &quot;StringItemList&quot;) Then _ControlModel.StringItemList = pvValue
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;TipText&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;TipText&quot;, V_STRING) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;HelpText&quot;) Then _ControlModel.HelpText = pvValue
+ Case UCase(&quot;TripleState&quot;)
+ Select Case _ControlType
+ Case CTLCHECKBOX
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;TripleState&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;TriState&quot;) Then _ControlModel.TriState = pvValue
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Value&quot;)
+ Select Case _ControlType
+ Case CTLBUTTON &apos;Boolean, toggle buttons only
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;Toggle&quot;) And oSession.HasUnoProperty(_ControlModel, &quot;State&quot;) Then
+ _ControlModel.State = Iif(pvValue, 1, 0)
+ End If
+ Case CTLCHECKBOX &apos;0 = Not checked, 1 = Checked, 2 = Don&apos;t know
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, Array(ScriptForge.V_BOOLEAN, ScriptForge.V_NUMERIC), Array(0, 1, 2, True, False)) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;State&quot;) Then
+ If VarType(pvValue) = ScriptForge.V_BOOLEAN Then pvValue = Iif(pvValue, 1, 0)
+ _ControlModel.State = pvValue
+ End If
+ Case CTLCOMBOBOX, CTLFILECONTROL, CTLPATTERNFIELD, CTLTEXTFIELD &apos;String
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, V_STRING) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;Text&quot;) Then _ControlModel.Text = pvValue
+ Case CTLCURRENCYFIELD, CTLNUMERICFIELD &apos;Numeric
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;Value&quot;) Then _ControlModel.Value = pvValue
+ Case CTLDATEFIELD &apos;Date
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, V_DATE) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;Date&quot;) Then
+ Set vSet = New com.sun.star.util.Date
+ vSet.Year = Year(pvValue)
+ vSet.Month = Month(pvValue)
+ vSet.Day = Day(pvValue)
+ _ControlModel.Date = vSet
+ End If
+ Case CTLFORMATTEDFIELD &apos;String or numeric
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, Array(V_STRING, ScriptForge.V_NUMERIC)) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;EffectiveValue&quot;) Then _ControlModel.EffectiveValue = pvValue
+ Case CTLLISTBOX &apos;String or array of strings depending on MultiSelection
+ &apos; StringItemList is the list of the items displayed in the box
+ &apos; SelectedItems is the list of the indexes in StringItemList of the selected items
+ &apos; It can go beyond the limits of StringItemList
+ &apos; It can contain multiple values even if the listbox is not multiselect
+ If oSession.HasUnoProperty(_ControlModel, &quot;StringItemList&quot;) And oSession.HasUnoProperty(_ControlModel, &quot;SelectedItems&quot;) _
+ And oSession.HasUnoProperty(_ControlModel, &quot;MultiSelection&quot;) Then
+ vSelection = Array()
+ If _ControlModel.MultiSelection Then
+ If Not ScriptForge.SF_Utils._ValidateArray(pvValue, &quot;Value&quot;, 1, V_STRING, True) Then GoTo Finally
+ vList = _ControlModel.StringItemList
+ For i = LBound(pvValue) To UBound(pvValue)
+ sItem = pvValue(i)
+ lIndex = ScriptForge.SF_Array.IndexOf(vList, sItem)
+ If lIndex &gt;= 0 Then vSelection = ScriptForge.SF_Array.Append(vSelection, lIndex)
+ Next i
+ Else
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, V_STRING) Then GoTo Finally
+ lIndex = ScriptForge.SF_Array.IndexOf(_ControlModel.StringItemList, pvValue)
+ If lIndex &gt;= 0 Then vSelection = Array(lIndex)
+ End If
+ _ControlModel.SelectedItems = vSelection
+ End If
+ Case CTLPROGRESSBAR &apos;Numeric
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;ProgressValueMin&quot;) Then
+ If pvValue &lt; _ControlModel.ProgressValueMin Then pvValue = _ControlModel.ProgressValueMin
+ End If
+ If oSession.HasUnoProperty(_ControlModel, &quot;ProgressValueMax&quot;) Then
+ If pvValue &gt; _ControlModel.ProgressValueMax Then pvValue = _ControlModel.ProgressValueMax
+ End If
+ If oSession.HasUnoProperty(_ControlModel, &quot;ProgressValue&quot;) Then _ControlModel.ProgressValue = pvValue
+ Case CTLRADIOBUTTON &apos;Boolean
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;State&quot;) Then _ControlModel.State = Iif(pvValue, 1, 0)
+ Case CTLSCROLLBAR &apos;Numeric
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;ScrollValueMin&quot;) Then
+ If pvValue &lt; _ControlModel.ScrollValueMin Then pvValue = _ControlModel.ScrollValueMin
+ End If
+ If oSession.HasUnoProperty(_ControlModel, &quot;ScrollValueMax&quot;) Then
+ If pvValue &gt; _ControlModel.ScrollValueMax Then pvValue = _ControlModel.ScrollValueMax
+ End If
+ If oSession.HasUnoProperty(_ControlModel, &quot;ScrollValue&quot;) Then _ControlModel.ScrollValue = pvValue
+ Case CTLTIMEFIELD
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, V_DATE) Then GoTo Finally
+ If oSession.HasUnoProperty(_ControlModel, &quot;Time&quot;) Then
+ Set vSet = New com.sun.star.util.Time
+ vSet.Hours = Hour(pvValue)
+ vSet.Minutes = Minute(pvValue)
+ vSet.Seconds = Second(pvValue)
+ _ControlModel.Time = vSet
+ End If
+ Case Else : GoTo CatchType
+ End Select
+ Case UCase(&quot;Visible&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Visible&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+ If oSession.HasUnoMethod(_ControlView, &quot;setVisible&quot;) Then
+ If pvValue Then
+ If oSession.HasUnoProperty(_ControlModel, &quot;EnableVisible&quot;) Then _ControlModel.EnableVisible = True
+ End If
+ _ControlView.setVisible(pvValue)
+ End If
+ Case Else
+ bSet = False
+ End Select
+
+Finally:
+ _PropertySet = bSet
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+CatchType:
+ ScriptForge.SF_Exception.RaiseFatal(CONTROLTYPEERROR, _Name, _DialogName, _ControlType, psProperty)
+ GoTo Finally
+End Function &apos; SFDialogs.SF_DialogControl._PropertySet
+
+REM -----------------------------------------------------------------------------
+Private Function _Repr() As String
+&apos;&apos;&apos; Convert the Model instance to a readable string, typically for debugging purposes (DebugPrint ...)
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Return:
+&apos;&apos;&apos; &quot;[DIALOGCONTROL]: Name, Type (dialogname)
+ _Repr = &quot;[DIALOGCONTROL]: &quot; &amp; _Name &amp; &quot;, &quot; &amp; _ControlType &amp; &quot; (&quot; &amp; _DialogName &amp; &quot;)&quot;
+
+End Function &apos; SFDialogs.SF_DialogControl._Repr
+
+REM ============================================ END OF SFDIALOGS.SF_DIALOGCONTROL
+</script:module> \ No newline at end of file
diff --git a/wizards/source/sfdialogs/SF_DialogListener.xba b/wizards/source/sfdialogs/SF_DialogListener.xba
new file mode 100644
index 000000000..0f324b609
--- /dev/null
+++ b/wizards/source/sfdialogs/SF_DialogListener.xba
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
+<script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_DialogListener" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
+REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
+REM === The SFDialogs library is one of the associated libraries. ===
+REM === Full documentation is available on https://help.libreoffice.org/ ===
+REM =======================================================================================================================
+
+Option Compatible
+Option Explicit
+
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+&apos;&apos;&apos; SF_Listener
+&apos;&apos;&apos; ===========
+&apos;&apos;&apos; The current module is dedicated to the management of dialog control events, triggered by user actions,
+&apos;&apos;&apos; which cannot be defined with the Basic IDE
+&apos;&apos;&apos;
+&apos;&apos;&apos; Concerned events:
+&apos;&apos;&apos; TreeControl control type
+&apos;&apos;&apos; -----------
+&apos;&apos;&apos; The OnNodeSelected event, triggered when a user selects a node
+&apos;&apos;&apos; A typical action is to display additional info about the selected item elsewhere in the dialog
+&apos;&apos;&apos; The OnNodeExpanded event, triggered when a user clicks on the expansion symbol
+&apos;&apos;&apos; A typical action is to create dynamically a subnode or a subtree below the expanded item
+&apos;&apos;&apos;
+&apos;&apos;&apos; The described events are processed thru UNO listeners
+&apos;&apos;&apos;
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+
+REM ================================================================= DEFINITIONS
+
+REM ================================================================== EXCEPTIONS
+
+REM ============================================================== PUBLIC METHODS
+
+REM -----------------------------------------------------------------------------
+Public Sub _SFEXP_requestChildNodes(Optional ByRef poEvent As Object)
+&apos;&apos;&apos; Triggered by the OnNodeExpanded event of a tree control
+&apos;&apos;&apos; The event is triggered thru a com.sun.star.view.XTreeExpansionListener
+&apos;&apos;&apos; The argument is passed to a user routine sstored in the SF_DialogControl instance
+&apos;&apos;&apos; as a scripting framework URI
+
+Dim oControl As Object &apos; The SF_DialogControl object having triggered the event
+
+ On Local Error GoTo Catch &apos; Avoid stopping event scripts
+
+Check:
+ &apos; Ensure there is a node
+ If IsNull(poEvent) Or IsMissing(poEvent) Then Exit Sub
+ If IsNull(poEvent.Node) Then Exit Sub
+
+Try:
+ Set oControl = ScriptForge.SF_Services.CreateScriptService(&quot;SFDialogs.DialogEvent&quot;, poEvent)
+ ScriptForge.SF_Session._ExecuteScript(oControl.OnNodeExpanded, poEvent)
+
+Finally:
+ Exit Sub
+Catch:
+ GoTo Finally
+End Sub
+
+Sub _SFEXP_disposing(ByRef poEvent As Object)
+End Sub
+
+Sub _SFEXP_treeExpanding(Optional ByRef poEvent As Object)
+End Sub
+
+Sub _SFEXP_treeCollapsing(ByRef poEvent As Object)
+End Sub
+
+Sub _SFEXP_treeExpanded(ByRef poEvent As Object)
+End Sub
+
+Sub _SFEXP_treeCollapsed(ByRef poEvent As Object)
+End Sub
+
+REM -----------------------------------------------------------------------------
+Public Sub _SFSEL_selectionChanged(Optional ByRef poEvent As Object)
+&apos;&apos;&apos; Triggered by the OnNodeSelected event of a tree control
+&apos;&apos;&apos; The event is triggered thru a com.sun.star.view.XSelectionChangeListener
+&apos;&apos;&apos; The argument is passed to a user routine sstored in the SF_DialogControl instance
+&apos;&apos;&apos; as a scripting framework URI
+&apos;&apos;&apos;
+&apos;&apos;&apos; Nothing happens if there are several selected nodes or none
+
+Dim vSelection As Variant &apos; Variant, not object !!
+Dim oControl As Object &apos; The SF_DialogControl object having triggered the event
+
+ On Local Error GoTo Catch &apos; Avoid stopping event scripts
+
+Check:
+ &apos; Ensure there is a selection
+ If IsNull(poEvent) Or IsMissing(poEvent) Then Exit Sub
+ vSelection = poEvent.Source.getSelection()
+ If IsEmpty(vSelection) Or IsArray(vSelection) Then Exit Sub
+
+Try:
+ Set oControl = ScriptForge.SF_Services.CreateScriptService(&quot;SFDialogs.DialogEvent&quot;, poEvent)
+ ScriptForge.SF_Session._ExecuteScript(oControl.OnNodeSelected, poEvent)
+
+Finally:
+ Exit Sub
+Catch:
+ GoTo Finally
+End Sub
+
+Sub _SFSEL_disposing(ByRef poEvent As Object)
+End Sub
+
+REM ============================================================= PRIVATE METHODS
+
+REM ============================================ END OF SFDIALOGS.SF_DIALOGLISTENER
+</script:module> \ No newline at end of file
diff --git a/wizards/source/sfdialogs/SF_Register.xba b/wizards/source/sfdialogs/SF_Register.xba
new file mode 100644
index 000000000..e81dbb069
--- /dev/null
+++ b/wizards/source/sfdialogs/SF_Register.xba
@@ -0,0 +1,348 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
+<script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_Register" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
+REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
+REM === The SFDialogs library is one of the associated libraries. ===
+REM === Full documentation is available on https://help.libreoffice.org/ ===
+REM =======================================================================================================================
+
+Option Compatible
+Option Explicit
+
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+&apos;&apos;&apos; SF_Register
+&apos;&apos;&apos; ===========
+&apos;&apos;&apos; The ScriptForge framework includes
+&apos;&apos;&apos; the master ScriptForge library
+&apos;&apos;&apos; a number of &quot;associated&quot; libraries SF*
+&apos;&apos;&apos; any user/contributor extension wanting to fit into the framework
+&apos;&apos;&apos;
+&apos;&apos;&apos; The main methods in this module allow the current library to cling to ScriptForge
+&apos;&apos;&apos; - RegisterScriptServices
+&apos;&apos;&apos; Register the list of services implemented by the current library
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+
+REM ================================================================= DEFINITIONS
+
+&apos;&apos;&apos; Event management of dialogs requires to being able to rebuild a Dialog object
+&apos;&apos;&apos; from its com.sun.star.awt.XControl - stardiv.Toolkit.UnoDialogControl UNO instance
+&apos;&apos;&apos; For that purpose, the started dialogs are buffered in a global array of _DialogCache types
+
+Type _DialogCache
+ Terminated As Boolean
+ XUnoDialog As Object
+ BasicDialog As Object
+End Type
+
+REM ================================================================== EXCEPTIONS
+
+Private Const DIALOGNOTFOUNDERROR = &quot;DIALOGNOTFOUNDERROR&quot;
+
+REM ============================================================== PUBLIC METHODS
+
+REM -----------------------------------------------------------------------------
+Public Sub RegisterScriptServices() As Variant
+&apos;&apos;&apos; Register into ScriptForge the list of the services implemented by the current library
+&apos;&apos;&apos; Each library pertaining to the framework must implement its own version of this method
+&apos;&apos;&apos;
+&apos;&apos;&apos; It consists in successive calls to the RegisterService() and RegisterEventManager() methods
+&apos;&apos;&apos; with 2 arguments:
+&apos;&apos;&apos; ServiceName: the name of the service as a case-insensitive string
+&apos;&apos;&apos; ServiceReference: the reference as an object
+&apos;&apos;&apos; If the reference refers to a module, then return the module as an object:
+&apos;&apos;&apos; GlobalScope.Library.Module
+&apos;&apos;&apos; If the reference is a class instance, then return a string referring to the method
+&apos;&apos;&apos; containing the New statement creating the instance
+&apos;&apos;&apos; &quot;libraryname.modulename.function&quot;
+
+ With GlobalScope.ScriptForge.SF_Services
+ .RegisterService(&quot;Dialog&quot;, &quot;SFDialogs.SF_Register._NewDialog&quot;) &apos; Reference to the function initializing the service
+ .RegisterEventManager(&quot;DialogEvent&quot;, &quot;SFDialogs.SF_Register._EventManager&quot;) &apos; Reference to the events manager
+ &apos;TODO
+ End With
+
+End Sub &apos; SFDialogs.SF_Register.RegisterScriptServices
+
+REM =========================================================== PRIVATE FUNCTIONS
+
+REM -----------------------------------------------------------------------------
+Private Function _AddDialogToCache(ByRef pvUnoDialog As Object _
+ , ByRef pvBasicDialog As Object _
+ ) As Long
+&apos;&apos;&apos; Add a new entry in the cache array with the references of the actual dialog
+&apos;&apos;&apos; If relevant, the last entry of the cache is reused.
+&apos;&apos;&apos; The cache is located in the global _SF_ variable
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; pvUnoDialog: the com.sun.star.awt.XControl - stardiv.Toolkit.UnoDialogControl of the dialog box
+&apos;&apos;&apos; pvBasicDialog: its corresponding Basic object
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The index of the new or modified entry
+
+Dim vCache As New _DialogCache &apos; Entry to be added
+Dim lIndex As Long &apos; UBound of _SF_.SFDialogs
+Dim vCacheArray As Variant &apos; Alias of _SF_.SFDialogs
+
+Try:
+ vCacheArray = _SF_.SFDialogs
+
+ If IsEmpty(vCacheArray) Then vCacheArray = Array()
+ lIndex = UBound(vCacheArray)
+ If lIndex &lt; LBound(vCacheArray) Then
+ ReDim vCacheArray(0 To 0)
+ lIndex = 0
+ ElseIf Not vCacheArray(lIndex).Terminated Then &apos; Often last entry can be reused
+ lIndex = lIndex + 1
+ ReDim Preserve vCacheArray(0 To lIndex)
+ End If
+
+ With vCache
+ .Terminated = False
+ Set .XUnoDialog = pvUnoDialog
+ Set .BasicDialog = pvBasicDialog
+ End With
+ vCacheArray(lIndex) = vCache
+
+ _SF_.SFDialogs = vCacheArray
+
+Finally:
+ _AddDialogToCache = lIndex
+ Exit Function
+End Function &apos; SFDialogs.SF_Register._AddDialogToCache
+
+REM -----------------------------------------------------------------------------
+Private Sub _CleanCacheEntry(ByVal plIndex As Long)
+&apos;&apos;&apos; Clean the plIndex-th entry in the dialogs cache
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; plIndex: must fit within the actual boundaries of the cache, otherwise the request is ignored
+
+Dim vCache As New _DialogCache &apos; Cleaned entry
+
+ With _SF_
+ If Not IsArray(.SFDialogs) Then Exit Sub
+ If plIndex &lt; LBound(.SFDialogs) Or plIndex &gt; UBound(.SFDialogs) Then Exit Sub
+
+ With vCache
+ .Terminated = True
+ Set .XUnoDialog = Nothing
+ Set .BasicDialog = Nothing
+ End With
+ .SFDialogs(plIndex) = vCache
+ End With
+
+Finally:
+ Exit Sub
+End Sub &apos; SFDialogs.SF_Register._CleanCacheEntry
+
+REM -----------------------------------------------------------------------------
+Public Function _EventManager(Optional ByRef pvArgs As Variant) As Object
+&apos;&apos;&apos; Returns a Dialog or DialogControl object corresponding with the Basic dialog
+&apos;&apos;&apos; which triggered the event in argument
+&apos;&apos;&apos; This method should be triggered only thru the invocation of CreateScriptService
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; pvEvent: com.sun.star.xxx
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; the output of a Dialog or DialogControl service or Nothing
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Sub TriggeredByEvent(ByRef poEvent As Object)
+&apos;&apos;&apos; Dim oDlg As Object
+&apos;&apos;&apos; Set oDlg = CreateScriptService(&quot;SFDialogs.DialogEvent&quot;, poEvent)
+&apos;&apos;&apos; If Not IsNull(oDlg) Then
+&apos;&apos;&apos; &apos; ... (a valid dialog or one of its controls has been identified)
+&apos;&apos;&apos; End Sub
+
+Dim oSource As Object &apos; Return value
+Dim oEventSource As Object &apos; Event UNO source
+Dim vEvent As Variant &apos; Alias of pvArgs(0)
+Dim sSourceType As String &apos; Implementation name of event source
+Dim oDialog As Object &apos; com.sun.star.awt.XControl - stardiv.Toolkit.UnoDialogControl
+Dim bControl As Boolean &apos; True when control event
+
+ &apos; Never abort while an event is processed
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Finally
+ Set oSource = Nothing
+
+Check:
+ If IsMissing(pvArgs) Or IsEmpty(pvArgs) Then pvArgs = Array()
+ If UBound(pvArgs) &gt;= 0 Then vEvent = pvArgs(0) Else vEvent = Empty
+ If VarType(vEvent) &lt;&gt; ScriptForge.V_OBJECT Then GoTo Finally
+ If Not ScriptForge.SF_Session.HasUnoProperty(vEvent, &quot;Source&quot;) Then GoTo Finally
+
+Try:
+ Set oEventSource = vEvent.Source
+ sSourceType = ScriptForge.SF_Session.UnoObjectType(oEventSource)
+
+ Set oDialog = Nothing
+ Select Case True
+ Case sSourceType = &quot;stardiv.Toolkit.UnoDialogControl&quot; &apos; A dialog
+ &apos; Search the dialog in the cache
+ Set oDialog = _FindDialogInCache(oEventSource)
+ bControl = False
+ Case Left(sSourceType, 16) = &quot;stardiv.Toolkit.&quot; &apos; A dialog control
+ Set oDialog = _FindDialogInCache(oEventSource.Context)
+ bControl = True
+ Case Else
+ End Select
+
+ If Not IsNull(oDialog) Then
+ If bControl Then Set oSource = oDialog.Controls(oEventSource.Model.Name) Else Set oSource = oDialog
+ End If
+
+Finally:
+ Set _EventManager = oSource
+ Exit Function
+End Function &apos; SFDialogs.SF_Register._EventManager
+
+REM -----------------------------------------------------------------------------
+Private Function _FindDialogInCache(ByRef poDialog As Object) As Object
+&apos;&apos;&apos; Find the dialog based on its XUnoDialog
+&apos;&apos;&apos; The dialog must not be terminated
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The corresponding Basic dialog part or Nothing
+
+Dim oBasicDialog As Object &apos; Return value
+Dim oCache As _DialogCache &apos; Entry in the cache
+
+ Set oBasicDialog = Nothing
+
+Try:
+ For Each oCache In _SF_.SFDialogs
+ If EqualUnoObjects(poDialog, oCache.XUnoDialog) And Not oCache.Terminated Then
+ Set oBasicDialog = oCache.BasicDialog
+ Exit For
+ End If
+ Next oCache
+
+Finally:
+ Set _FindDialogInCache = oBasicDialog
+ Exit Function
+End Function &apos; SFDialogs.SF_Register._FindDialogInCache
+
+REM -----------------------------------------------------------------------------
+Public Function _NewDialog(Optional ByVal pvArgs As Variant) As Object
+&apos;&apos;&apos; Create a new instance of the SF_Dialog class
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Container: either &quot;GlobalScope&quot; or a WindowName. Default = the active window
+&apos;&apos;&apos; see the definition of WindowName in the description of the UI service
+&apos;&apos;&apos; Library: the name of the library hosting the dialog. Default = &quot;Standard&quot;
+&apos;&apos;&apos; DialogName: The name of the dialog
+&apos;&apos;&apos; Library and dialog names are case-sensitive
+&apos;&apos;&apos; Context: When called from Python, the context must be provided : XSCRIPTCONTEXT
+&apos;&apos;&apos; Returns: the instance or Nothing
+
+Dim oDialog As Object &apos; Return value
+Dim vContainer As Variant &apos; Alias of pvArgs(0)
+Dim vLibrary As Variant &apos; Alias of pvArgs(1)
+Dim vDialogName As Variant &apos; Alias of pvArgs(2)
+Dim oLibraries As Object &apos; com.sun.star.comp.sfx2.DialogLibraryContainer
+Dim vContext As Variant &apos; com.sun.star.uno.XComponentContext
+Dim oDialogProvider As Object &apos; com.sun.star.io.XInputStreamProvider
+Dim oEnum As Object &apos; com.sun.star.container.XEnumeration
+Dim oComp As Object &apos; com.sun.star.lang.XComponent
+Dim oDialogControl As Object &apos; com.sun.star.awt.XControl - stardiv.Toolkit.UnoDialogControl
+Dim vWindow As Window &apos; A single component
+Dim sScope As String &apos; &quot;application&quot; or &quot;document&quot;
+Dim sURI As String &apos; URI of the targeted dialog
+Dim oUi As Object &apos; &quot;UI&quot; service
+Dim bFound As Boolean &apos; True if WindowName is found on the desktop
+Const cstService = &quot;SFDialogs.Dialog&quot;
+Const cstGlobal = &quot;GlobalScope&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+Check:
+ If IsMissing(pvArgs) Or IsEmpty(pvArgs) Then pvArgs = Array()
+ If Not IsArray(pvArgs) Then pvArgs = Array(pvArgs) &apos; Needed when _NewDialog called from _EventManager
+ If UBound(pvArgs) &gt;= 0 Then vContainer = pvArgs(0) Else vContainer = &quot;&quot;
+ If UBound(pvArgs) &gt;= 1 Then vLibrary = pvArgs(1)
+ If IsEmpty(vLibrary) Then vLibrary = &quot;Standard&quot;
+ If UBound(pvArgs) &gt;= 2 Then vDialogName = pvArgs(2) Else vDialogName = Empty &apos; Use Empty to force mandatory status
+ If Not ScriptForge.SF_Utils._Validate(vContainer, &quot;Container&quot;, Array(V_STRING, ScriptForge.V_OBJECT)) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(vLibrary, &quot;Library&quot;, V_STRING) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(vDialogName, &quot;DialogName&quot;, V_STRING) Then GoTo Finally
+ If UBound(pvArgs) &gt;= 3 Then vContext = pvArgs(3) Else vContext = Nothing
+ If Not ScriptForge.SF_Utils._Validate(vContext, &quot;DialogName&quot;, V_OBJECT) Then GoTo Finally
+ Set oDialog = Nothing
+
+Try:
+ &apos; Determine the library container hosting the dialog
+ Set oUi = ScriptForge.SF_Register.CreateScriptService(&quot;UI&quot;)
+ Set oComp = Nothing
+ If VarType(vContainer) = V_STRING Then
+ bFound = ( UCase(vContainer) = UCase(cstGlobal) )
+ End If
+ If Not bFound Then
+ Select Case VarType(vContainer)
+ Case V_STRING
+ If Len(vContainer) &gt; 0 Then
+ bFound = False
+ Set oEnum = StarDesktop.Components().createEnumeration
+ Do While oEnum.hasMoreElements
+ Set oComp = oEnum.nextElement
+ vWindow = oUi._IdentifyWindow(oComp)
+ With vWindow
+ &apos; Does the current window match the argument ?
+ If (Len(.WindowFileName) &gt; 0 And .WindowFileName = ScriptForge.SF_FileSystem._ConvertToUrl(vContainer)) _
+ Or (Len(.WindowName) &gt; 0 And .WindowName = vContainer) _
+ Or (Len(.WindowTitle) &gt; 0 And .WindowTitle = vContainer) Then
+ bFound = True
+ Exit Do
+ End If
+ End With
+ Loop
+ Else
+ bFound = True
+ Set oComp = StarDesktop.CurrentComponent
+ vWindow = oUi._IdentifyWindow(oComp)
+ End If
+ Case V_OBJECT &apos; com.sun.star.lang.XComponent
+ bFound = True
+ vWindow = oUi._IdentifyWindow(vContainer)
+ Set oComp = vContainer
+ End Select
+ If Not bFound Then GoTo CatchNotFound
+ If Len(vWindow.DocumentType) = 0 Then GoTo CatchNotFound
+ End If
+
+ &apos; Determine the dialog provider
+ Select Case True
+ Case IsNull(vContext) And IsNull(oComp) &apos; Basic and GlobalScope
+ Set oDialogProvider = GetProcessServiceManager.createInstance(&quot;com.sun.star.awt.DialogProvider&quot;)
+ Case IsNull(vContext) And Not IsNull(oComp) &apos; Basic and Document
+ Set oDialogProvider = GetProcessServiceManager.createInstanceWithArguments(&quot;com.sun.star.awt.DialogProvider&quot;, Array(oComp))
+ Case Not IsNull(vContext) And IsNull(oComp) &apos; Python and GlobalScope
+ Set oDialogProvider = vContext.getServiceManager().createInstanceWithContext(&quot;com.sun.star.awt.DialogProvider&quot;, vContext)
+ Case Not IsNull(vContext) And Not IsNull(oComp) &apos; Python and Document
+ Set oDialogProvider = vContext.getServiceManager().createInstanceWithArguments(&quot;com.sun.star.awt.DialogProvider&quot;, Array(oComp))
+ End Select
+
+ &apos; Create the graphical interface
+ sScope = Iif(IsNull(oComp), &quot;application&quot;, &quot;document&quot;)
+ sURI = &quot;vnd.sun.star.script:&quot; &amp; vLibrary &amp; &quot;.&quot; &amp; vDialogName &amp; &quot;?location=&quot; &amp; sScope
+ On Local Error GoTo CatchNotFound
+ Set oDialogControl = oDialogProvider.createDialog(sURI)
+
+ &apos; Initialize the basic SF_Dialog instance to return to the user script
+ Set oDialog = New SF_Dialog
+ With oDialog
+ Set .[Me] = oDialog
+ If VarType(vContainer) = V_STRING Then ._Container = vContainer Else ._Container = vWindow.WindowName
+ ._Library = vLibrary
+ ._Name = vDialogName
+ Set ._DialogProvider = oDialogProvider
+ Set ._DialogControl = oDialogControl
+ ._Initialize()
+ End With
+
+Finally:
+ Set _NewDialog = oDialog
+ Exit Function
+Catch:
+ GoTo Finally
+CatchNotFound:
+ ScriptForge.SF_Exception.RaiseFatal(DIALOGNOTFOUNDERROR, &quot;Service&quot;, cstService _
+ , &quot;Container&quot;, vContainer, &quot;Library&quot;, vLibrary, &quot;DialogName&quot;, vDialogName)
+ GoTo Finally
+End Function &apos; SFDialogs.SF_Register._NewDialog
+
+REM ============================================== END OF SFDIALOGS.SF_REGISTER
+</script:module> \ No newline at end of file
diff --git a/wizards/source/sfdialogs/__License.xba b/wizards/source/sfdialogs/__License.xba
new file mode 100644
index 000000000..e98be710e
--- /dev/null
+++ b/wizards/source/sfdialogs/__License.xba
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
+<script:module xmlns:script="http://openoffice.org/2000/script" script:name="__License" script:language="StarBasic" script:moduleType="normal">
+&apos;&apos;&apos; Copyright 2019-2022 Jean-Pierre LEDURE, Rafael LIMA, Alain ROMEDENNE
+
+REM =======================================================================================================================
+REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
+REM === The SFDialogs library is one of the associated libraries. ===
+REM === Full documentation is available on https://help.libreoffice.org/ ===
+REM =======================================================================================================================
+
+&apos;&apos;&apos; ScriptForge is distributed in the hope that it will be useful,
+&apos;&apos;&apos; but WITHOUT ANY WARRANTY; without even the implied warranty of
+&apos;&apos;&apos; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+&apos;&apos;&apos; ScriptForge is free software; you can redistribute it and/or modify it under the terms of either (at your option):
+
+&apos;&apos;&apos; 1) The Mozilla Public License, v. 2.0. If a copy of the MPL was not
+&apos;&apos;&apos; distributed with this file, you can obtain one at http://mozilla.org/MPL/2.0/ .
+
+&apos;&apos;&apos; 2) The GNU Lesser General Public License as published by
+&apos;&apos;&apos; the Free Software Foundation, either version 3 of the License, or
+&apos;&apos;&apos; (at your option) any later version. If a copy of the LGPL was not
+&apos;&apos;&apos; distributed with this file, see http://www.gnu.org/licenses/ .
+
+</script:module> \ No newline at end of file
diff --git a/wizards/source/sfdialogs/dialog.xlb b/wizards/source/sfdialogs/dialog.xlb
new file mode 100644
index 000000000..be8e58d45
--- /dev/null
+++ b/wizards/source/sfdialogs/dialog.xlb
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "library.dtd">
+<library:library xmlns:library="http://openoffice.org/2000/library" library:name="SFDialogs" library:readonly="false" library:passwordprotected="false"/> \ No newline at end of file
diff --git a/wizards/source/sfdialogs/script.xlb b/wizards/source/sfdialogs/script.xlb
new file mode 100644
index 000000000..6dff54d87
--- /dev/null
+++ b/wizards/source/sfdialogs/script.xlb
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "library.dtd">
+<library:library xmlns:library="http://openoffice.org/2000/library" library:name="SFDialogs" library:readonly="false" library:passwordprotected="false">
+ <library:element library:name="__License"/>
+ <library:element library:name="SF_Register"/>
+ <library:element library:name="SF_Dialog"/>
+ <library:element library:name="SF_DialogControl"/>
+ <library:element library:name="SF_DialogListener"/>
+</library:library> \ No newline at end of file