<?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;	Control initial position and dimensions in APPFONT units
Private _Left				As Long
Private _Top				As Long
Private _Width				As Long
Private _Height				As Long

&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;	Updatable events
Private _ActionListener		As Object		&apos; com.sun.star.awt.XActionListener
Private _OnActionPerformed	As String		&apos; Script to invoke when action triggered
Private _ActionCounter		As Integer		&apos; Counts the number of events set on the listener
&apos; ---
Private _AdjustmentListener	As Object		&apos; com.sun.star.awt.XAdjustmentListener
Private _OnAdjustmentValueChanged As String	&apos; Script to invoke when scrollbar value has changed
Private _AdjustmentCounter	As Integer		&apos; Counts the number of events set on the listener
&apos; ---
Private _FocusListener		As Object		&apos; com.sun.star.awt.XFocusListener
Private _OnFocusGained		As String		&apos; Script to invoke when control gets focus
Private _OnFocusLost		As String		&apos; Script to invoke when control loses focus
Private _FocusCounter		As Integer		&apos; Counts the number of events set on the listener
&apos; ---
Private _ItemListener		As Object		&apos; com.sun.star.awt.XItemListener
Private _OnItemStateChanged	As String		&apos; Script to invoke when status of item changes
Private _ItemCounter		As Integer		&apos; Counts the number of events set on the listener
&apos; ---
Private _KeyListener		As Object		&apos; com.sun.star.awt.XKeyListener
Private _OnKeyPressed		As String		&apos; Script to invoke when Key clicked in control
Private _OnKeyReleased		As String		&apos; Script to invoke when Key released in control
Private _KeyCounter			As Integer		&apos; Counts the number of events set on the listener
&apos; ---
Private _MouseListener		As Object		&apos; com.sun.star.awt.XMouseListener
Private _OnMouseEntered		As String		&apos; Script to invoke when mouse enters control
Private _OnMouseExited		As String		&apos; Script to invoke when mouse leaves control
Private _OnMousePressed		As String		&apos; Script to invoke when mouse clicked in control
Private _OnMouseReleased	As String		&apos; Script to invoke when mouse released in control
Private _MouseCounter		As Integer		&apos; Counts the number of events set on the listener
&apos; ---
Private _MouseMotionListener As Object		&apos; com.sun.star.awt.XMouseMotionListener
Private _OnMouseDragged		As String		&apos; Script to invoke when mouse is dragged from the control
Private _OnMouseMoved		As String		&apos; Script to invoke when mouse is moved across the control
Private _MouseMotionCounter	As Integer	&apos; Counts the number of events set on the listener
&apos; ---
Private _TextListener		As Object		&apos; com.sun.star.awt.XTextListener
Private _OnTextChanged		As String		&apos; Script to invoke when textual content has changed
Private _TextCounter		As Integer		&apos; Counts the number of events set on the listener

&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 CTLHYPERLINK		= &quot;Hyperlink&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;

	_Left = SF_DialogUtils.MINPOSITION
	_Top = SF_DialogUtils.MINPOSITION
	_Width = -1
	_Height = -1

	_OnNodeSelected = &quot;&quot;
	_OnNodeExpanded = &quot;&quot;
	Set _SelectListener = Nothing
	Set _ExpandListener = Nothing

	Set _ActionListener = Nothing
	_OnActionPerformed = &quot;&quot;
	_ActionCounter = 0
	Set _AdjustmentListener = Nothing
	_OnAdjustmentValueChanged = &quot;&quot;
	_AdjustmentCounter = 0
	Set _FocusListener = Nothing
	_OnFocusGained = &quot;&quot;
	_OnFocusLost = &quot;&quot;
	_FocusCounter = 0
	Set _KeyListener = Nothing
	_OnKeyPressed = &quot;&quot;
	_OnKeyReleased = &quot;&quot;
	_KeyCounter = 0
	Set _MouseListener = Nothing
	_OnMouseEntered = &quot;&quot;
	_OnMouseExited = &quot;&quot;
	_OnMousePressed = &quot;&quot;
	_OnMouseReleased = &quot;&quot;
	_MouseCounter = 0
	Set _MouseMotionListener = Nothing
	_OnMouseDragged = &quot;&quot;
	_OnMouseMoved = &quot;&quot;
	_MouseMotionCounter = 0
	Set _ItemListener = Nothing
	_OnItemStateChanged = &quot;&quot;
	_ItemCounter = 0
	Set _TextListener = Nothing
	_OnTextChanged = &quot;&quot;
	_TextCounter = 0

	_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 Border() As Variant
&apos;&apos;&apos;	The Border property refers to the surrounding of the control: 3D, FLAT or NONE
	Border = _PropertyGet(&quot;Border&quot;, &quot;&quot;)
End Property	&apos;	SFDialogs.SF_DialogControl.Border (get)

REM -----------------------------------------------------------------------------
Property Let Border(Optional ByVal pvBorder As Variant)
&apos;&apos;&apos;	Set the updatable property Border
	_PropertySet(&quot;Border&quot;, pvBorder)
End Property	&apos;	SFDialogs.SF_DialogControl.Border (let)

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
	_PropertySet(&quot;Format&quot;, pvFormat)
End Property	&apos;	SFDialogs.SF_DialogControl.Format (let)

REM -----------------------------------------------------------------------------
Property Get Height() As Variant
&apos;&apos;&apos;	The Height property refers to the height of the control
	Height = _PropertyGet(&quot;Height&quot;)
End Property	&apos;	SFDialogs.SF_DialogControl.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_DialogControl.Height (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 Let OnActionPerformed(Optional ByVal pvActionPerformed As Variant)
&apos;&apos;&apos;	Set the updatable property OnActionPerformed
	_PropertySet(&quot;OnActionPerformed&quot;, pvActionPerformed)
End Property	&apos;	SFDialogs.SF_DialogControl.OnActionPerformed (let)

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 Let OnAdjustmentValueChanged(Optional ByVal pvAdjustmentValueChanged As Variant)
&apos;&apos;&apos;	Set the updatable property OnAdjustmentValueChanged
	_PropertySet(&quot;OnAdjustmentValueChanged&quot;, pvAdjustmentValueChanged)
End Property	&apos;	SFDialogs.SF_DialogControl.OnAdjustmentValueChanged (let)

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 Let OnFocusGained(Optional ByVal pvOnFocusGained As Variant)
&apos;&apos;&apos;	Set the updatable property OnFocusGained
	_PropertySet(&quot;OnFocusGained&quot;, pvOnFocusGained)
End Property	&apos;	SFDialogs.SF_DialogControl.OnFocusGained (let)

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 Let OnFocusLost(Optional ByVal pvOnFocusLost As Variant)
&apos;&apos;&apos;	Set the updatable property OnFocusLost
	_PropertySet(&quot;OnFocusLost&quot;, pvOnFocusLost)
End Property	&apos;	SFDialogs.SF_DialogControl.OnFocusLost (let)

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 Let OnItemStateChanged(Optional ByVal pvItemStateChanged As Variant)
&apos;&apos;&apos;	Set the updatable property OnItemStateChanged
	_PropertySet(&quot;OnItemStateChanged&quot;, pvItemStateChanged)
End Property	&apos;	SFDialogs.SF_DialogControl.OnItemStateChanged (let)

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 Let OnKeyPressed(Optional ByVal pvOnKeyPressed As Variant)
&apos;&apos;&apos;	Set the updatable property OnKeyPressed
	_PropertySet(&quot;OnKeyPressed&quot;, pvOnKeyPressed)
End Property	&apos;	SFDialogs.SF_DialogControl.OnKeyPressed (let)

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 Let OnKeyReleased(Optional ByVal pvOnKeyReleased As Variant)
&apos;&apos;&apos;	Set the updatable property OnKeyReleased
	_PropertySet(&quot;OnKeyReleased&quot;, pvOnKeyReleased)
End Property	&apos;	SFDialogs.SF_DialogControl.OnKeyReleased (let)

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 Let OnMouseDragged(Optional ByVal pvOnMouseDragged As Variant)
&apos;&apos;&apos;	Set the updatable property OnMouseDragged
	_PropertySet(&quot;OnMouseDragged&quot;, pvOnMouseDragged)
End Property	&apos;	SFDialogs.SF_DialogControl.OnMouseDragged (let)

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 Let OnMouseEntered(Optional ByVal pvOnMouseEntered As Variant)
&apos;&apos;&apos;	Set the updatable property OnMouseEntered
	_PropertySet(&quot;OnMouseEntered&quot;, pvOnMouseEntered)
End Property	&apos;	SFDialogs.SF_DialogControl.OnMouseEntered (let)

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 Let OnMouseExited(Optional ByVal pvOnMouseExited As Variant)
&apos;&apos;&apos;	Set the updatable property OnMouseExited
	_PropertySet(&quot;OnMouseExited&quot;, pvOnMouseExited)
End Property	&apos;	SFDialogs.SF_DialogControl.OnMouseExited (let)

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 Let OnMouseMoved(Optional ByVal pvOnMouseMoved As Variant)
&apos;&apos;&apos;	Set the updatable property OnMouseMoved
	_PropertySet(&quot;OnMouseMoved&quot;, pvOnMouseMoved)
End Property	&apos;	SFDialogs.SF_DialogControl.OnMouseMoved (let)

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 Let OnMousePressed(Optional ByVal pvOnMousePressed As Variant)
&apos;&apos;&apos;	Set the updatable property OnMousePressed
	_PropertySet(&quot;OnMousePressed&quot;, pvOnMousePressed)
End Property	&apos;	SFDialogs.SF_DialogControl.OnMousePressed (let)

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 Let OnMouseReleased(Optional ByVal pvOnMouseReleased As Variant)
&apos;&apos;&apos;	Set the updatable property OnMouseReleased
	_PropertySet(&quot;OnMouseReleased&quot;, pvOnMouseReleased)
End Property	&apos;	SFDialogs.SF_DialogControl.OnMouseReleased (let)

REM -----------------------------------------------------------------------------
Property Get OnNodeExpanded() As Variant
&apos;&apos;&apos;	Get the script associated with the OnNodeExpanded event
	OnNodeExpanded = _PropertyGet(&quot;OnNodeExpanded&quot;)
End Property	&apos;	SFDialogs.SF_DialogControl.OnNodeExpanded (get)

REM -----------------------------------------------------------------------------
Property Let OnNodeExpanded(Optional ByVal pvOnNodeExpanded As Variant)
&apos;&apos;&apos;	Set the updatable property OnNodeExpanded
	_PropertySet(&quot;OnNodeExpanded&quot;, pvOnNodeExpanded)
End Property	&apos;	SFDialogs.SF_DialogControl.OnNodeExpanded (let)

REM -----------------------------------------------------------------------------
Property Get OnNodeSelected() As Variant
&apos;&apos;&apos;	Get the script associated with the OnNodeSelected event
	OnNodeSelected = _PropertyGet(&quot;OnNodeSelected&quot;)
End Property	&apos;	SFDialogs.SF_DialogControl.OnNodeSelected (get)

REM -----------------------------------------------------------------------------
Property Let OnNodeSelected(Optional ByVal pvOnNodeSelected As Variant)
&apos;&apos;&apos;	Set the updatable property OnNodeSelected
	_PropertySet(&quot;OnNodeSelected&quot;, pvOnNodeSelected)
End Property	&apos;	SFDialogs.SF_DialogControl.OnNodeSelected (let)

REM -----------------------------------------------------------------------------
Property Get OnTextChanged() As Variant
&apos;&apos;&apos;	Get the script associated with the OnTextChanged event
	OnTextChanged = _PropertyGet(&quot;OnTextChanged&quot;)
End Property	&apos;	SFDialogs.SF_DialogControl.OnTextChanged (get)

REM -----------------------------------------------------------------------------
Property Let OnTextChanged(Optional ByVal pvTextChanged As Variant)
&apos;&apos;&apos;	Set the updatable property OnTextChanged
	_PropertySet(&quot;OnTextChanged&quot;, pvTextChanged)
End Property	&apos;	SFDialogs.SF_DialogControl.OnTextChanged (let)

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 TabIndex() As Variant
&apos;&apos;&apos;	The TabIndex property specifies a control&apos;s place in the tab order in the dialog
&apos;&apos;&apos;	Zero or negative means no tab set in the control
	TabIndex = _PropertyGet(&quot;TabIndex&quot;, -1)
End Property	&apos;	SFDialogs.SF_DialogControl.TabIndex (get)

REM -----------------------------------------------------------------------------
Property Let TabIndex(Optional ByVal pvTabIndex As Variant)
&apos;&apos;&apos;	Set the updatable property TabIndex
	_PropertySet(&quot;TabIndex&quot;, pvTabIndex)
End Property	&apos;	SFDialogs.SF_DialogControl.TabIndex (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 URL() As Variant
&apos;&apos;&apos;	The URL property refers to the URL to open when the control is clicked
	URL = _PropertyGet(&quot;URL&quot;, &quot;&quot;)
End Property	&apos;	SFDialogs.SF_DialogControl.URL (get)

REM -----------------------------------------------------------------------------
Property Let URL(Optional ByVal pvURL As Variant)
&apos;&apos;&apos;	Set the updatable property URL
	_PropertySet(&quot;URL&quot;, pvURL)
End Property	&apos;	SFDialogs.SF_DialogControl.URL (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 Width() As Variant
&apos;&apos;&apos;	The Width property refers to the Width of the control
	Width = _PropertyGet(&quot;Width&quot;)
End Property	&apos;	SFDialogs.SF_DialogControl.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_DialogControl.Width (let)

REM -----------------------------------------------------------------------------
Property Get X() As Variant
&apos;&apos;&apos;	The X property refers to the X coordinate of the top-left corner of the control
	X = _PropertyGet(&quot;X&quot;)
End Property	&apos;	SFDialogs.SF_DialogControl.X (get)

REM -----------------------------------------------------------------------------
Property Let X(Optional ByVal pvX As Variant)
&apos;&apos;&apos;	Set the updatable property X
	_PropertySet(&quot;X&quot;, pvX)
End Property	&apos;	SFDialogs.SF_DialogControl.X (let)

REM -----------------------------------------------------------------------------
Property Get Y() As Variant
&apos;&apos;&apos;	The Y property refers to the Y coordinate of the top-left corner of the control
	Y = _PropertyGet(&quot;Y&quot;)
End Property	&apos;	SFDialogs.SF_DialogControl.Y (get)

REM -----------------------------------------------------------------------------
Property Let Y(Optional ByVal pvY As Variant)
&apos;&apos;&apos;	Set the updatable property Y
	_PropertySet(&quot;Y&quot;, pvY)
End Property	&apos;	SFDialogs.SF_DialogControl.Y (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;Border&quot; _
					, &quot;Cancel&quot; _
					, &quot;Caption&quot; _
					, &quot;ControlType&quot; _
					, &quot;CurrentNode&quot; _
					, &quot;Default&quot; _
					, &quot;Enabled&quot; _
					, &quot;Format&quot; _
					, &quot;Height&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;TabIndex&quot; _
					, &quot;Text&quot; _
					, &quot;TipText&quot; _
					, &quot;TripleState&quot; _
					, &quot;URL&quot; _
					, &quot;Value&quot; _
					, &quot;Visible&quot; _
					, &quot;Width&quot; _
					, &quot;X&quot; _
					, &quot;XControlModel&quot; _
					, &quot;XControlView&quot; _
					, &quot;XGridColumnModel&quot; _
					, &quot;XGridDataModel&quot; _
					, &quot;XTreeDataModel&quot; _
					, &quot;Y&quot; _
					)

End Function	&apos;	SFDialogs.SF_DialogControl.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 the control to new coordinates and/or modify its dimensions
&apos;&apos;&apos;	Without arguments, the method resets the initial dimensions and position
&apos;&apos;&apos;	Attributes denoting the position and size of a control are expressed in &quot;Map AppFont&quot; units.
&apos;&apos;&apos;	Map AppFont units are device and resolution independent.
&apos;&apos;&apos;	One Map AppFont unit is equal to one eighth of the average character (Systemfont) height and one quarter of the average character width.
&apos;&apos;&apos;	The dialog editor (= the Basic IDE) also uses Map AppFont units.
&apos;&apos;&apos;	Args:
&apos;&apos;&apos;		Left : the horizontal distance from the top-left corner. It may be negative.
&apos;&apos;&apos;		Top : the vertical distance from the top-left corner. It may be negative.
&apos;&apos;&apos;		Width : the horizontal width of the rectangle containing the Dialog. It must be positive.
&apos;&apos;&apos;		Height : the vertical height of the rectangle containing the Dialog. It must be positive.
&apos;&apos;&apos;		Missing arguments are left unchanged.
&apos;&apos;&apos;	Returns:
&apos;&apos;&apos;		True when successful
&apos;&apos;&apos;	Examples:
&apos;&apos;&apos;		myControl.Resize(100, 200, Height := 600)	&apos;	Width is not changed

Try:
	Resize = SF_DialogUtils._Resize([Me], Left, Top, Width, Height)

End Function	&apos;	SFDialogss.SF_Dialog.Resize

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 _
								, Optional ByVal RowHeaderWidth 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 one data 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 available space in 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;		RowGeaderWidth: width of the row header column expressed in AppFont units. Default = 10.
&apos;&apos;&apos;				The argument is ignored when the TableControl has no row header.
&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 lHeaderWidth As Long		&apos;	Row header width when row header present, otherwise = 0
Dim lAverageWidth As Long		&apos;	Width to apply when columns spread evenly across table
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 cstThisSub = &quot;SFDialogs.DialogControl.SetTableData&quot;
Const cstSubArgs = &quot;DataArray, [Widths=Array(1)], [Alignments=&quot;&quot;&quot;&quot;], [RowHeaderWidth=10]&quot;

	If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
	bData = False

Check:
	If IsMissing(Widths) Or IsEmpty(Widths) Then Widths = Array()
	If IsMissing(Alignments) Or IsEmpty(Alignments) Then Alignments = &quot;&quot;
	If IsMissing(RowHeaderWidth) Or IsEmpty(RowHeaderWidth) Then RowHeaderWidth = 10
	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
		If Not ScriptForge.SF_Utils._Validate(RowHeaderWidth, &quot;RowHeaderWidth&quot;, ScriptForge.V_NUMERIC) 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 Python
	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;	Manage row headers width
	If _ControlModel.ShowRowHeader Then
		lHeaderWidth = RowHeaderWidth
		_ControlModel.RowHeaderWidth = lHeaderWidth
	Else
		lHeaderWidth = 0
	End If

	&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 column widths
		If dRelativeWidth &gt; 0.0 Then dWidthFactor = CDbl(_ControlModel.Width - lHeaderWidth) / 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 header and columns evenly
		lAverageWidth = (_ControlModel.Width - lHeaderWidth) / (lMax2 - lMin2 + 1)
		For j = 0 To lMax2 - lMinCol
			_GridColumnModel.Columns(j).ColumnWidth = lAverageWidth
		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 -----------------------------------------------------------------------------
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;UnoControlFixedHyperlinkModel&quot;
			_ControlType = CTLHYPERLINK
		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 initial position and dimensions
	With _ControlModel
		_Left = .PositionX
		_Top = .PositionY
		_Width = .Width
		_Height = .Height
	End With

	&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 oPosSize As Object						&apos;	com.sun.star.awt.Rectangle
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;Border&quot;)
			Select Case _ControlType
				Case CTLCOMBOBOX, CTLCURRENCYFIELD, CTLDATEFIELD, CTLFILECONTROL, CTLFIXEDTEXT, CTLFORMATTEDFIELD _
						, CTLHYPERLINK, CTLIMAGECONTROL, CTLLISTBOX, CTLNUMERICFIELD, CTLPATTERNFIELD, CTLPROGRESSBAR _
						, CTLSCROLLBAR , CTLTABLECONTROL, CTLTEXTFIELD, CTLTIMEFIELD, CTLTREECONTROL
					If oSession.HasUNOProperty(_ControlModel, &quot;Border&quot;) Then _PropertyGet = Array(&quot;NONE&quot;, &quot;3D&quot;, &quot;FLAT&quot;)(_ControlModel.Border)
				Case CTLCHECKBOX, CTLRADIOBUTTON
					If oSession.HasUNOProperty(_ControlModel, &quot;VisualEffect&quot;) Then _PropertyGet = Array(&quot;NONE&quot;, &quot;3D&quot;, &quot;FLAT&quot;)(_ControlModel.VisualEffect)
				Case Else	:	GoTo CatchType
			End Select
		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, CTLHYPERLINK, 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 = SF_DialogUtils._FormatsList(_ControlType)(_ControlModel.DateFormat)
				Case CTLTIMEFIELD
					If oSession.HasUNOProperty(_ControlModel, &quot;TimeFormat&quot;) Then _PropertyGet = SF_DialogUtils._FormatsList(_ControlType)(_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;Height&quot;)
			If [_parent]._Displayed Then	&apos;	Convert PosSize view property from pixels to APPFONT units
				_PropertyGet = SF_DialogUtils._ConvertToAppFont(_ControlView, False).Height
			Else
				If oSession.HasUNOProperty(_ControlModel, &quot;Height&quot;) Then _PropertyGet = _ControlModel.Height
			End If			
		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
				&apos;	Check OnEvents set dynamically by code
				Select Case UCase(psProperty)
					Case UCase(&quot;OnActionPerformed&quot;)			:	_PropertyGet = _OnActionPerformed
					Case UCase(&quot;OnAdjustmentValueChanged&quot;)	:	_PropertyGet = _OnAdjustmentValueChanged
					Case UCase(&quot;OnFocusGained&quot;)				:	_PropertyGet = _OnFocusGained
					Case UCase(&quot;OnFocusLost&quot;)				:	_PropertyGet = _OnFocusLost
					Case UCase(&quot;OnItemStateChanged&quot;)		:	_PropertyGet = _OnItemStateChanged
					Case UCase(&quot;OnKeyPressed&quot;)				:	_PropertyGet = _OnKeyPressed
					Case UCase(&quot;OnKeyReleased&quot;)				:	_PropertyGet = _OnKeyReleased
					Case UCase(&quot;OnMouseDragged&quot;)			:	_PropertyGet = _OnMouseDragged
					Case UCase(&quot;OnMouseEntered&quot;)			:	_PropertyGet = _OnMouseEntered
					Case UCase(&quot;OnMouseExited&quot;)				:	_PropertyGet = _OnMouseExited
					Case UCase(&quot;OnMouseMoved&quot;)				:	_PropertyGet = _OnMouseMoved
					Case UCase(&quot;OnMousePressed&quot;)			:	_PropertyGet = _OnMousePressed
					Case UCase(&quot;OnMouseReleased&quot;)			:	_PropertyGet = _OnMouseReleased
					Case UCase(&quot;OnTextChanged&quot;)				:	_PropertyGet = _OnTextChanged
					Case Else								:	_PropertyGet = &quot;&quot;
				End Select
			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;TabIndex&quot;)
			Select Case _ControlType
				Case CTLBUTTON, CTLCHECKBOX, CTLCOMBOBOX, CTLCURRENCYFIELD, CTLDATEFIELD, CTLFILECONTROL, CTLFIXEDTEXT _
						, CTLFORMATTEDFIELD, CTLHYPERLINK, CTLIMAGECONTROL, CTLLISTBOX, CTLNUMERICFIELD, CTLPATTERNFIELD _
						, CTLRADIOBUTTON, CTLSCROLLBAR, CTLTABLECONTROL, CTLTEXTFIELD, CTLTIMEFIELD, CTLTREECONTROL
					If oSession.HasUnoProperty(_ControlModel, &quot;TabIndex&quot;) Then
						If CBool(_ControlModel.TabStop) Or IsEmpty(_ControlModel.TabStop) Then _PropertyGet = _ControlModel.TabIndex Else _PropertyGet = -1
					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 &quot;URL&quot;
			Select Case _ControlType
				Case CTLHYPERLINK
					If oSession.HasUnoProperty(_ControlModel, &quot;URL&quot;) Then _PropertyGet = _ControlModel.URL
				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;) And _ControlMOdel.Toggle 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;Width&quot;)
			If [_parent]._Displayed Then	&apos;	Convert PosSize view property from pixels to APPFONT units
				_PropertyGet = SF_DialogUtils._ConvertToAppFont(_ControlView, False).Width
			Else
				If oSession.HasUNOProperty(_ControlModel, &quot;Width&quot;) Then _PropertyGet = _ControlModel.Width
			End If
		Case UCase(&quot;X&quot;)
			If [_parent]._Displayed Then	&apos;	Convert PosSize view property from pixels to APPFONT units
				_PropertyGet = SF_DialogUtils._ConvertToAppFont(_ControlView, True).X
			Else
				If oSession.HasUNOProperty(_ControlModel, &quot;PositionX&quot;) Then _PropertyGet = _ControlModel.PositionX
			End If
		Case UCase(&quot;Y&quot;)
			If [_parent]._Displayed Then	&apos;	Convert PosSize view property from pixels to APPFONT units
				_PropertyGet = SF_DialogUtils._ConvertToAppFont(_ControlView, True).Y
			Else
				If oSession.HasUNOProperty(_ControlModel, &quot;PositionY&quot;) Then _PropertyGet = _ControlModel.PositionY
			End If
		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 vBorders As Variant						&apos;	Array of allowed Border values
Dim vFormats As Variant						&apos;	Format property: output of _FormatsList()
Dim iFormat As Integer						&apos;	Format property: index in vFormats
Dim oNumberFormats As Object				&apos;	com.sun.star.util.XNumberFormats
Dim lFormatKey As Long						&apos;	Format index for formatted fields
Dim oLocale As Object						&apos;	com.sun.star.lang.Locale
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;Border&quot;)
			Select Case _ControlType
				Case CTLCHECKBOX, CTLCOMBOBOX, CTLCURRENCYFIELD, CTLDATEFIELD, CTLFILECONTROL, CTLFIXEDTEXT, CTLFORMATTEDFIELD _
						, CTLHYPERLINK, CTLIMAGECONTROL, CTLLISTBOX, CTLNUMERICFIELD, CTLPATTERNFIELD, CTLPROGRESSBAR _
						, CTLRADIOBUTTON, CTLSCROLLBAR , CTLTABLECONTROL, CTLTEXTFIELD, CTLTIMEFIELD, CTLTREECONTROL
					vBorders = Array(&quot;NONE&quot;, &quot;3D&quot;, &quot;FLAT&quot;)
					If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Border&quot;, V_STRING, vBorders) Then GoTo Finally
					vSet = ScriptForge.SF_Array.IndexOf(vBorders, pvValue)
					If oSession.HasUNOProperty(_ControlModel, &quot;Border&quot;) Then
						_ControlModel.Border = vSet
					ElseIf oSession.HasUNOProperty(_ControlModel, &quot;VisualEffect&quot;) Then	&apos;	Checkbox case
						_ControlModel.VisualEffect = vSet
					End If
				Case Else	:	GoTo CatchType
			End Select
		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, CTLHYPERLINK, 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 = SF_DialogUtils._FormatsList(_ControlType)
					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 CTLFORMATTEDFIELD		&apos;	The format may exist already or not yet
					If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Format&quot;, V_STRING) Then GoTo Finally
					If oSession.HasUNOProperty(_ControlModel, &quot;FormatsSupplier&quot;) Then
						If Not IsNull(_ControlModel.FormatsSupplier) Then
							Set oLocale = ScriptForge.SF_Utils._GetUnoService(&quot;FormatLocale&quot;)
							Set oNumberFormats = _ControlModel.FormatsSupplier.getNumberFormats()
							lFormatKey = oNumberFormats.queryKey(pvValue, oLocale, True)
							If lFormatKey &lt; 0 Then		&apos;	Format not found
								_ControlModel.FormatKey = oNumberFormats.addNew(pvValue, oLocale)
							Else
								_ControlModel.FormatKey = lFormatKey
							End If
						End If
					End If
				Case Else	:	GoTo CatchType
			End Select
		Case UCase(&quot;Height&quot;)
			If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Height&quot;, ScriptForge.V_NUMERIC) Then GoTo Catch
			bSet = Resize(Height := pvValue)
		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;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;)
			If Not ScriptForge.SF_Utils._Validate(pvValue, psProperty, V_STRING) Then GoTo Catch
			&apos;	Check control type for not universal event types
			Select Case UCase(psProperty)
				Case UCase(&quot;OnActionPerformed&quot;), UCase(&quot;OnItemStateChanged&quot;)
					Select Case _ControlType
						Case CTLBUTTON, CTLCHECKBOX, CTLCOMBOBOX, CTLHYPERLINK, CTLLISTBOX, CTLRADIOBUTTON
						Case Else	:	GoTo CatchType
					End Select
				Case UCase(&quot;OnAdjustmentValueChanged&quot;)
					If _ControlType &lt;&gt; CTLSCROLLBAR Then GoTo CatchType
				Case UCase(&quot;OnTextChanged&quot;)
					Select Case _ControlType
						Case CTLCOMBOBOX, CTLCURRENCYFIELD, CTLDATEFIELD, CTLFILECONTROL, CTLFORMATTEDFIELD _
								, CTLNUMERICFIELD, CTLPATTERNFIELD, CTLTEXTFIELD, CTLTIMEFIELD, CTLTREECONTROL
						Case Else	:	GoTo CatchType
					End Select
				Case Else
			End Select
			bSet = SF_DialogListener._SetOnProperty([Me], psProperty, pvValue)
		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;TabIndex&quot;)
			Select Case _ControlType
				Case CTLBUTTON, CTLCHECKBOX, CTLCOMBOBOX, CTLCURRENCYFIELD, CTLDATEFIELD, CTLFILECONTROL, CTLFIXEDTEXT _
						, CTLFORMATTEDFIELD, CTLHYPERLINK, CTLIMAGECONTROL, CTLLISTBOX, CTLNUMERICFIELD, CTLPATTERNFIELD _
						, CTLRADIOBUTTON, CTLSCROLLBAR, CTLTABLECONTROL, CTLTEXTFIELD, CTLTIMEFIELD, CTLTREECONTROL
					If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;TabIndex&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
					If oSession.HasUnoProperty(_ControlModel, &quot;TabIndex&quot;) Then
						_ControlModel.TabStop = ( pvValue  &gt; 0 )
						_ControlModel.TabIndex = Iif(pvValue &gt; 0, pvValue, -1)
					End If
				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 &quot;URL&quot;
			Select Case _ControlType
				Case CTLHYPERLINK
					If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;URL&quot;, V_STRING) Then GoTo Finally
					If oSession.HasUnoProperty(_ControlModel, &quot;URL&quot;) Then _ControlModel.URL = 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
						If _ControlModel.Toggle Then _ControlModel.State = Iif(pvValue, 1, 0) Else _ControlModel.State = 2
					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 UCase(&quot;Width&quot;)
			If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Width&quot;, ScriptForge.V_NUMERIC) Then GoTo Catch
			bSet = Resize(Width := pvValue)
		Case &quot;X&quot;
			If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Width&quot;, ScriptForge.V_NUMERIC) Then GoTo Catch
			bSet = Resize(Left := pvValue)
		Case &quot;Y&quot;
			If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Width&quot;, ScriptForge.V_NUMERIC) Then GoTo Catch
			bSet = Resize(Top := pvValue)
		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>