summaryrefslogtreecommitdiffstats
path: root/wizards/source/sfdocuments/SF_Register.xba
diff options
context:
space:
mode:
Diffstat (limited to 'wizards/source/sfdocuments/SF_Register.xba')
-rw-r--r--wizards/source/sfdocuments/SF_Register.xba546
1 files changed, 546 insertions, 0 deletions
diff --git a/wizards/source/sfdocuments/SF_Register.xba b/wizards/source/sfdocuments/SF_Register.xba
new file mode 100644
index 000000000..5baf37afb
--- /dev/null
+++ b/wizards/source/sfdocuments/SF_Register.xba
@@ -0,0 +1,546 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
+<script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_Register" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
+REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
+REM === The SFDocuments library is one of the associated libraries. ===
+REM === Full documentation is available on https://help.libreoffice.org/ ===
+REM =======================================================================================================================
+
+Option Compatible
+Option Explicit
+
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+&apos;&apos;&apos; SF_Register
+&apos;&apos;&apos; ===========
+&apos;&apos;&apos; The ScriptForge framework includes
+&apos;&apos;&apos; the master ScriptForge library
+&apos;&apos;&apos; a number of &quot;associated&quot; libraries SF*
+&apos;&apos;&apos; any user/contributor extension wanting to fit into the framework
+&apos;&apos;&apos;
+&apos;&apos;&apos; The main methods in this module allow the current library to cling to ScriptForge
+&apos;&apos;&apos; - RegisterScriptServices
+&apos;&apos;&apos; Register the list of services implemented by the current library
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+
+REM ================================================================== EXCEPTIONS
+
+REM ================================================================= DEFINITIONS
+
+&apos;&apos;&apos; Strategy for management of Form and FormControl events:
+&apos;&apos;&apos; ------------------------------------------------------
+&apos;&apos;&apos; At the contrary of Dialogs and DialogControls, which are always started from some code,
+&apos;&apos;&apos; Forms and FormControls will be initiated most often by the user, even if the SFDocuments library
+&apos;&apos;&apos; allows to start forms programmatically
+&apos;&apos;&apos;
+&apos;&apos;&apos; For Forms started programmatically, the corresponding objects are built top-down
+&apos;&apos;&apos; Event management of forms and their controls requires to being able to rebuild Form
+&apos;&apos;&apos; and FormControl objects bottom-up
+&apos;&apos;&apos;
+&apos;&apos;&apos; To avoid multiple rebuilds requested by multiple events,
+&apos;&apos;&apos; 1. The active form objects are cached in a global array of _FormCache types
+&apos;&apos;&apos; 2. FormControl objects are cached in Form objects
+&apos;&apos;&apos; 3. The bottom-up rebuild is executed only once, at instance creation
+
+Type _FormCache
+ Terminated As Boolean
+ XUnoForm As Object
+ BasicForm As Object
+End Type
+
+REM ============================================================== PUBLIC METHODS
+
+REM -----------------------------------------------------------------------------
+Public Sub RegisterScriptServices() As Variant
+&apos;&apos;&apos; Register into ScriptForge the list of the services implemented by the current library
+&apos;&apos;&apos; Each library pertaining to the framework must implement its own version of this method
+&apos;&apos;&apos;
+&apos;&apos;&apos; It consists in successive calls to the RegisterService() and RegisterEventManager() methods
+&apos;&apos;&apos; with 2 arguments:
+&apos;&apos;&apos; ServiceName: the name of the service as a case-insensitive string
+&apos;&apos;&apos; ServiceReference: the reference as an object
+&apos;&apos;&apos; If the reference refers to a module, then return the module as an object:
+&apos;&apos;&apos; GlobalScope.Library.Module
+&apos;&apos;&apos; If the reference is a class instance, then return a string referring to the method
+&apos;&apos;&apos; containing the New statement creating the instance
+&apos;&apos;&apos; &quot;libraryname.modulename.function&quot;
+
+ With GlobalScope.ScriptForge.SF_Services
+ .RegisterService(&quot;Document&quot;, &quot;SFDocuments.SF_Register._NewDocument&quot;) &apos; Reference to the function initializing the service
+ .RegisterService(&quot;Base&quot;, &quot;SFDocuments.SF_Register._NewDocument&quot;) &apos; Same reference, distinction is made inside the function
+ .RegisterService(&quot;Calc&quot;, &quot;SFDocuments.SF_Register._NewDocument&quot;) &apos; Same reference, distinction is made inside the function
+ .RegisterService(&quot;Writer&quot;, &quot;SFDocuments.SF_Register._NewDocument&quot;) &apos; Same reference, distinction is made inside the function
+ .RegisterEventManager(&quot;DocumentEvent&quot;, &quot;SFDocuments.SF_Register._EventManager&quot;) &apos; Reference to the events manager
+ .RegisterEventManager(&quot;FormEvent&quot;, &quot;SFDocuments.SF_Register._FormEventManager&quot;)&apos; Reference to the form and controls events manager
+ End With
+
+End Sub &apos; SFDocuments.SF_Register.RegisterScriptServices
+
+REM =========================================================== PRIVATE FUNCTIONS
+
+REM -----------------------------------------------------------------------------
+Private Function _AddFormToCache(ByRef pvUnoForm As Object _
+ , ByRef pvBasicForm As Object _
+ ) As Long
+&apos;&apos;&apos; Add a new entry in the cache array with the references of the actual Form
+&apos;&apos;&apos; If relevant, the last entry of the cache is reused.
+&apos;&apos;&apos; The cache is located in the global _SF_ variable
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; pvUnoForm: com.sun.star.form.XForm or com.sun.star.comp.forms.ODatabaseForm
+&apos;&apos;&apos; pvBasicForm: its corresponding Basic object
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The index of the new or modified entry
+
+Dim vCache As New _FormCache &apos; Entry to be added
+Dim lIndex As Long &apos; UBound of _SF_.SFForms
+Dim vCacheArray As Variant &apos; Alias of _SF_.SFForms
+
+Try:
+ vCacheArray = _SF_.SFForms
+
+ If IsEmpty(vCacheArray) Then vCacheArray = Array()
+ lIndex = UBound(vCacheArray)
+ If lIndex &lt; LBound(vCacheArray) Then
+ ReDim vCacheArray(0 To 0)
+ lIndex = 0
+ ElseIf Not vCacheArray(lIndex).Terminated Then &apos; Often last entry can be reused
+ lIndex = lIndex + 1
+ ReDim Preserve vCacheArray(0 To lIndex)
+ End If
+
+ With vCache
+ .Terminated = False
+ Set .XUnoForm = pvUnoForm
+ Set .BasicForm = pvBasicForm
+ End With
+ Set vCacheArray(lIndex) = vCache
+
+ _SF_.SFForms = vCacheArray
+
+Finally:
+ _AddFormToCache = lIndex
+ Exit Function
+End Function &apos; SFDocuments.SF_Register._AddFormToCache
+
+REM -----------------------------------------------------------------------------
+Private Sub _CleanCacheEntry(ByVal plIndex As Long)
+&apos;&apos;&apos; Clean the plIndex-th entry in the Forms cache
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; plIndex: must fit within the actual boundaries of the cache, otherwise the request is ignored
+
+Dim vCache As New _FormCache &apos; Cleaned entry
+
+ With _SF_
+ If Not IsArray(.SFForms) Then Exit Sub
+ If plIndex &lt; LBound(.SFForms) Or plIndex &gt; UBound(.SFForms) Then Exit Sub
+
+ With vCache
+ .Terminated = True
+ Set .XUnoForm = Nothing
+ Set .BasicForm = Nothing
+ End With
+ .SFForms(plIndex) = vCache
+ End With
+
+Finally:
+ Exit Sub
+End Sub &apos; SFDocuments.SF_Register._CleanCacheEntry
+
+REM -----------------------------------------------------------------------------
+Public Function _EventManager(Optional ByRef pvArgs As Variant) As Object
+&apos;&apos;&apos; Returns a Document, Calc or Base object corresponding with the active component
+&apos;&apos;&apos; which triggered the event in argument
+&apos;&apos;&apos; This method should be triggered only thru the invocation of CreateScriptService
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; pvEvent: com.sun.star.document.DocumentEvent
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; the output of a Document, Calc, ... service or Nothing
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Sub TriggeredByEvent(ByRef poEvent As Object)
+&apos;&apos;&apos; Dim oDoc As Object
+&apos;&apos;&apos; Set oDoc = CreateScriptService(&quot;SFDocuments.DocumentEvent&quot;, poEvent)
+&apos;&apos;&apos; If Not IsNull(oDoc) Then
+&apos;&apos;&apos; &apos; ... (a valid document has been identified)
+&apos;&apos;&apos; End Sub
+
+Dim oSource As Object &apos; Return value
+Dim vEvent As Variant &apos; Alias of pvArgs(0)
+
+ &apos; Never abort while an event is processed
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Finally
+ Set oSource = Nothing
+
+Check:
+ If IsMissing(pvArgs) Or IsEmpty(pvArgs) Then pvArgs = Array()
+ If UBound(pvArgs) &gt;= 0 Then vEvent = pvArgs(0) Else Set vEvent = Empty
+ If VarType(vEvent) &lt;&gt; ScriptForge.V_OBJECT Then GoTo Finally
+
+Try:
+ If ScriptForge.SF_Session.UnoObjectType(vEvent) = &quot;com.sun.star.document.DocumentEvent&quot; Then
+ Set oSource = SF_Register._NewDocument(vEvent.Source)
+ End If
+
+Finally:
+ Set _EventManager = oSource
+ Exit Function
+End Function &apos; SFDocuments.SF_Register._EventManager
+
+REM -----------------------------------------------------------------------------
+Private Function _FindFormInCache(ByRef poForm As Object) As Object
+&apos;&apos;&apos; Find the Form based on its XUnoForm
+&apos;&apos;&apos; The Form must not be terminated
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The corresponding Basic Form part or Nothing
+
+Dim oBasicForm As Object &apos; Return value
+Dim oCache As _FormCache &apos; Entry in the cache
+
+ Set oBasicForm = Nothing
+
+Try:
+ With _SF_
+ If Not IsEmpty(.SFForms) Then
+ For Each oCache In .SFForms
+ If EqualUnoObjects(poForm, oCache.XUnoForm) And Not oCache.Terminated Then
+ Set oBasicForm = oCache.BasicForm
+ Exit For
+ End If
+ Next oCache
+ End If
+ End With
+
+Finally:
+ Set _FindFormInCache = oBasicForm
+ Exit Function
+End Function &apos; SFDocuments.SF_Register._FindFormInCache
+
+REM -----------------------------------------------------------------------------
+Public Function _FormEventManager(Optional ByRef pvArgs As Variant) As Object
+&apos;&apos;&apos; Returns a Form or FormControl object corresponding with the form or control
+&apos;&apos;&apos; which triggered the event in argument
+&apos;&apos;&apos; This method should be triggered only thru the invocation of CreateScriptService
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; pvEvent: com.sun.star.lang.EventObject
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; the output of a Form, FormControl service or Nothing
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Sub TriggeredByEvent(ByRef poEvent As Object)
+&apos;&apos;&apos; Dim oForm As Object
+&apos;&apos;&apos; Set oForm = CreateScriptService(&quot;SFDocuments.FormEvent&quot;, poEvent)
+&apos;&apos;&apos; If Not IsNull(oForm) Then
+&apos;&apos;&apos; &apos; ... (a valid form or subform has been identified)
+&apos;&apos;&apos; End Sub
+
+Dim oSource As Object &apos; Return value
+Dim vEvent As Variant &apos; Alias of pvArgs(0)
+Dim oControlModel As Object &apos; com.sun.star.awt.XControlModel
+Dim oParent As Object &apos; com.sun.star.form.OGridControlModel or com.sun.star.comp.forms.ODatabaseForm
+Dim sParentType As String &apos; &quot;com.sun.star.form.OGridControlModel&quot; or &quot;com.sun.star.comp.forms.ODatabaseForm&quot;
+Dim oSFParent As Object &apos; The parent as a ScriptForge instance: SF_Form or SF_FormControl
+Dim oSFForm As Object &apos; The grand-parent SF_Form instance
+Dim oSession As Object : Set oSession = ScriptForge.SF_Session
+
+ &apos; Never abort while an event is processed
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Finally
+ Set oSource = Nothing
+
+Check:
+ If IsMissing(pvArgs) Or IsEmpty(pvArgs) Then pvArgs = Array()
+ If UBound(pvArgs) &gt;= 0 Then vEvent = pvArgs(0) Else Set vEvent = Empty
+ If VarType(vEvent) &lt;&gt; ScriptForge.V_OBJECT Then GoTo Finally
+
+Try:
+ If oSession.HasUnoProperty(vEvent, &quot;Source&quot;) Then
+
+ &apos; FORM EVENT
+ If oSession.UnoObjectType(vEvent.Source) = &quot;com.sun.star.comp.forms.ODatabaseForm&quot; Then
+ Set oSource = SF_Register._NewForm(vEvent.Source, pbForceInit := True)
+
+ &apos; CONTROL EVENT
+ Else
+ &apos; A SF_FormControl instance is always created from its parent, either a form, a subform or a table control
+ Set oControlModel = vEvent.Source.Model &apos; The event source is a control view com.sun.star.awt.XControl
+ Set oParent = oControlModel.Parent
+ sParentType = oSession.UnoObjectType(oParent)
+ Select Case sParentType
+ Case &quot;com.sun.star.form.OGridControlModel&quot;
+ Set oSFForm = SF_Register._NewForm(oParent.Parent, pbForceInit := True)
+ Set oSFParent = oSFForm.Controls(oParent.Name)
+ Case &quot;com.sun.star.comp.forms.ODatabaseForm&quot;
+ Set oSFParent = SF_Register._NewForm(oParent, pbForceInit := True)
+ End Select
+ &apos; The final instance is derived from its parent instance
+ Set oSource = oSFParent.Controls(oControlModel.Name)
+
+ End If
+
+ End If
+
+Finally:
+ Set _FormEventManager = oSource
+ Exit Function
+End Function &apos; SFDocuments.SF_Register._FormEventManager
+
+REM -----------------------------------------------------------------------------
+Public Function _GetEventScriptCode(poObject As Object _
+ , ByVal psEvent As String _
+ , ByVal psName As String _
+ ) As String
+&apos;&apos;&apos; Extract from the parent of poObject the Basic script linked to psEvent.
+&apos;&apos;&apos; Helper function common to forms and form controls
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; poObject: a com.sun.star.form.XForm or XControl object
+&apos;&apos;&apos; psEvent: the &quot;On...&quot; name of the event
+&apos;&apos;&apos; psName: the name of the object to be identified from the parent object
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The script to trigger when psEvent occurs
+&apos;&apos;&apos; See Scripting Framework URI Specification : https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification
+
+Dim vEvents As Variant &apos; List of available events in the parent object
+ &apos; Array of com.sun.star.script.ScriptEventDescriptor
+Dim sEvent As String &apos; The targeted event name
+Dim oParent As Object &apos; The parent object
+Dim lIndex As Long &apos; The index of the targeted event in the events list of the parent object
+Dim sName As String &apos; The corrected UNO event name
+Dim i As Long
+
+ _GetEventScriptCode = &quot;&quot;
+ On Local Error GoTo Catch
+ If Not ScriptForge.SF_Session.HasUnoMethod(poObject, &quot;getParent&quot;) Then GoTo Finally
+
+Try:
+ &apos; Find form index i.e. find control via getByIndex()
+ &apos; The name is known (= psName) but getByIndex() is not in the same sequence as getElementNames()
+ Set oParent = poObject.getParent()
+ lIndex = -1
+ For i = 0 To oParent.getCount() - 1
+ sName = oParent.getByIndex(i).Name
+ If (sName = psName) Then
+ lIndex = i
+ Exit For
+ End If
+ Next i
+ If lIndex &lt; 0 Then GoTo Finally &apos; Not found, should not happen
+
+ &apos; Find script triggered by event
+ vEvents = oParent.getScriptEvents(lIndex) &apos; Returns an array
+ &apos; Fix historical typo error
+ sEvent = Replace(LCase(Mid(psEvent, 3, 1)) &amp; Mid(psEvent, 4), &quot;errorOccurred&quot;, &quot;errorOccured&quot;)
+ For i = 0 To UBound(vEvents)
+ If vEvents(i).EventMethod = sEvent Then
+ _GetEventScriptCode = vEvents(i).ScriptCode
+ Exit For
+ End If
+ Next i
+
+Finally:
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDocuments.SF_Register._GetEventScriptCode
+
+REM -----------------------------------------------------------------------------
+Public Function _NewDocument(Optional ByVal pvArgs As Variant) As Object
+&apos;&apos;&apos; Create a new instance of the (super) SF_Document class or of one of its subclasses (SF_Calc, ...)
+&apos; Args:
+&apos;&apos;&apos; WindowName: see the definition of WindowName in the description of the UI service
+&apos;&apos;&apos; If absent, the document is presumed to be in the active window
+&apos;&apos;&apos; If WindowName is an object, it must be a component
+&apos;&apos;&apos; (com.sun.star.lang.XComponent or com.sun.star.comp.dba.ODatabaseDocument)
+&apos;&apos;&apos; Returns: the instance or Nothing
+
+Dim oDocument As Object &apos; Return value
+Dim oSuperDocument As Object &apos; Companion superclass document
+Dim vWindowName As Variant &apos; Alias of pvArgs(0)
+Dim oEnum As Object &apos; com.sun.star.container.XEnumeration
+Dim oComp As Object &apos; com.sun.star.lang.XComponent
+Dim vWindow As Window &apos; A single component
+Dim oUi As Object &apos; &quot;UI&quot; service
+Dim bFound As Boolean &apos; True if the document is found on the desktop
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+Check:
+ If IsMissing(pvArgs) Or IsEmpty(pvArgs) Then pvArgs = Array()
+ If Not IsArray(pvArgs) Then pvArgs = Array(pvArgs) &apos; Needed when _NewDocument called from _EventManager
+ If UBound(pvArgs) &gt;= 0 Then vWindowName = pvArgs(0) Else vWindowName = &quot;&quot;
+ If Not ScriptForge.SF_Utils._Validate(vWindowName, &quot;WindowName&quot;, Array(V_STRING, ScriptForge.V_OBJECT)) Then GoTo Finally
+ Set oDocument = Nothing
+
+Try:
+ Set oUi = ScriptForge.SF_Services.CreateScriptService(&quot;UI&quot;)
+ Select Case VarType(vWindowName)
+ Case V_STRING
+ If Len(vWindowName) &gt; 0 Then
+ bFound = False
+ Set oEnum = StarDesktop.Components().createEnumeration
+ Do While oEnum.hasMoreElements
+ Set oComp = oEnum.nextElement
+ vWindow = oUi._IdentifyWindow(oComp)
+ With vWindow
+ &apos; Does the current window match the argument ?
+ If (Len(.WindowFileName) &gt; 0 And .WindowFileName = ScriptForge.SF_FileSystem._ConvertToUrl(vWindowName)) _
+ Or (Len(.WindowName) &gt; 0 And .WindowName = vWindowName) _
+ Or (Len(.WindowTitle) &gt; 0 And .WindowTitle = vWindowName) Then
+ bFound = True
+ Exit Do
+ End If
+ End With
+ Loop
+ Else
+ bFound = True
+ vWindow = oUi._IdentifyWindow(StarDesktop.CurrentComponent)
+ End If
+ Case ScriptForge.V_OBJECT &apos; com.sun.star.lang.XComponent
+ bFound = True
+ vWindow = oUi._IdentifyWindow(vWindowName)
+ End Select
+
+ If bFound And Not IsNull(vWindow.Frame) And Len(vWindow.DocumentType) &gt; 0 Then
+ &apos; Create the right subclass and associate to it a new instance of the superclass
+ Select Case vWindow.DocumentType
+ Case &quot;Base&quot;
+ Set oDocument = New SF_Base
+ Set oSuperDocument = New SF_Document
+ Set oDocument.[_Super] = oSuperDocument &apos; Now both super and subclass are twinned
+ Set oSuperDocument.[_SubClass] = oDocument
+ Case &quot;Calc&quot;
+ Set oDocument = New SF_Calc
+ Set oSuperDocument = New SF_Document
+ Set oDocument.[_Super] = oSuperDocument &apos; Now both super and subclass are twinned
+ Set oSuperDocument.[_SubClass] = oDocument
+ Case &quot;Writer&quot;
+ Set oDocument = New SF_Writer
+ Set oSuperDocument = New SF_Document
+ Set oDocument.[_Super] = oSuperDocument &apos; Now both super and subclass are twinned
+ Set oSuperDocument.[_SubClass] = oDocument
+ Case Else &apos; Only superclass
+ Set oDocument = New SF_Document
+ Set oSuperDocument = oDocument
+ End Select
+ With oDocument &apos; Initialize attributes of subclass
+ Set .[Me] = oDocument
+ Set ._Component = vWindow.Component
+ &apos; Initialize specific attributes
+ Select Case vWindow.DocumentType
+ Case &quot;Base&quot;
+ Set ._DataSource = ._Component.DataSource
+ Case Else
+ End Select
+ End With
+ With oSuperDocument &apos; Initialize attributes of superclass
+ Set .[Me] = oSuperDocument
+ Set ._Component = vWindow.Component
+ Set ._Frame = vWindow.Frame
+ ._WindowName = vWindow.WindowName
+ ._WindowTitle = vWindow.WindowTitle
+ ._WindowFileName = vWindow.WindowFileName
+ ._DocumentType = vWindow.DocumentType
+ End With
+ End If
+
+Finally:
+ Set _NewDocument = oDocument
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDocuments.SF_Register._NewDocument
+
+REM -----------------------------------------------------------------------------
+Public Function _NewForm(ByRef poForm As Object _
+ , Optional pbForceInit As Boolean _
+ ) As Object
+&apos;&apos;&apos; Returns an existing or a new SF_Form instance based on the argument
+&apos;&apos;&apos; If the instance is new (not found in cache), the minimal members are initialized
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; poForm: com.sun.star.form.XForm or com.sun.star.comp.forms.ODatabaseForm
+&apos;&apos;&apos; pbForceInit: when True, initialize the form instance. Default = False
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; A SF_Form instance
+
+Dim oForm As Object &apos; Return value
+
+Try:
+ Set oForm = SF_Register._FindFormInCache(poForm)
+ If IsNull(oForm) Then &apos; Not found
+ If IsMissing(pbForceInit) Or IsEmpty(pbForceInit) Then pbForceInit = False
+ Set oForm = New SF_Form
+ With oForm
+ ._Name = poForm.Name
+ Set .[Me] = oForm
+ Set ._Form = poForm
+ If pbForceInit Then ._Initialize()
+ End With
+ End If
+
+Finally:
+ Set _NewForm = oForm
+ Exit Function
+End Function &apos; SFDocuments.SF_Register._NewForm
+
+REM -----------------------------------------------------------------------------
+Public Function _RegisterEventScript(poObject As Object _
+ , ByVal psEvent As String _
+ , ByVal psListener As String _
+ , ByVal psScriptCode As String _
+ , ByVal psName As String _
+ ) As Boolean
+&apos;&apos;&apos; Register a script event (psEvent) to poObject (Form, SubForm or Control)
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; poObject: a com.sun.star.form.XForm or XControl object
+&apos;&apos;&apos; psEvent: the &quot;On...&quot; name of the event
+&apos;&apos;&apos; psListener: the listener name corresponding with the event
+&apos;&apos;&apos; psScriptCode: The script to trigger when psEvent occurs
+&apos;&apos;&apos; See Scripting Framework URI Specification : https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification
+&apos;&apos;&apos; psName: the name of the object to associate with the event
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; True when successful
+
+Dim oEvent As Object &apos; com.sun.star.script.ScriptEventDescriptor
+Dim sEvent As String &apos; The targeted event name
+Dim oParent As Object &apos; The parent object
+Dim lIndex As Long &apos; The index of the targeted event in the events list of the parent object
+Dim sName As String &apos; The corrected UNO event name
+Dim i As Long
+
+ _RegisterEventScript = False
+ On Local Error GoTo Catch
+ If Not ScriptForge.SF_Session.HasUnoMethod(poObject, &quot;getParent&quot;) Then GoTo Finally
+
+Try:
+ &apos; Find object&apos;s internal index i.e. how to reach it via getByIndex()
+ Set oParent = poObject.getParent()
+ lIndex = -1
+ For i = 0 To oParent.getCount() - 1
+ sName = oParent.getByIndex(i).Name
+ If (sName = psName) Then
+ lIndex = i
+ Exit For
+ End If
+ Next i
+ If lIndex &lt; 0 Then GoTo Finally &apos; Not found, should not happen
+
+ &apos; Fix historical typo error
+ sEvent = Replace(LCase(Mid(psEvent, 3, 1)) &amp; Mid(psEvent, 4), &quot;errorOccurred&quot;, &quot;errorOccured&quot;)
+ &apos; Apply new script code. Erasing it is done with a specific UNO method
+ If psScriptCode = &quot;&quot; Then
+ oParent.revokeScriptEvent(lIndex, psListener, sEvent, &quot;&quot;)
+ Else
+ Set oEvent = CreateUnoStruct(&quot;com.sun.star.script.ScriptEventDescriptor&quot;)
+ With oEvent
+ .ListenerType = psListener
+ .EventMethod = sEvent
+ .ScriptType = &quot;Script&quot; &apos; Better than &quot;Basic&quot;
+ .ScriptCode = psScriptCode
+ End With
+ oParent.registerScriptEvent(lIndex, oEvent)
+ End If
+ _RegisterEventScript = True
+
+Finally:
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFDocuments.SF_Register._RegisterEventScript
+
+REM ============================================== END OF SFDOCUMENTS.SF_REGISTER
+</script:module> \ No newline at end of file