SF_Register.xba 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
  3. <script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_Register" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
  4. REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
  5. REM === The SFDocuments library is one of the associated libraries. ===
  6. REM === Full documentation is available on https://help.libreoffice.org/ ===
  7. REM =======================================================================================================================
  8. Option Compatible
  9. Option Explicit
  10. &apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
  11. &apos;&apos;&apos; SF_Register
  12. &apos;&apos;&apos; ===========
  13. &apos;&apos;&apos; The ScriptForge framework includes
  14. &apos;&apos;&apos; the master ScriptForge library
  15. &apos;&apos;&apos; a number of &quot;associated&quot; libraries SF*
  16. &apos;&apos;&apos; any user/contributor extension wanting to fit into the framework
  17. &apos;&apos;&apos;
  18. &apos;&apos;&apos; The main methods in this module allow the current library to cling to ScriptForge
  19. &apos;&apos;&apos; - RegisterScriptServices
  20. &apos;&apos;&apos; Register the list of services implemented by the current library
  21. &apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
  22. REM ================================================================== EXCEPTIONS
  23. REM ================================================================= DEFINITIONS
  24. &apos;&apos;&apos; Strategy for management of Form and FormControl events:
  25. &apos;&apos;&apos; ------------------------------------------------------
  26. &apos;&apos;&apos; At the contrary of Dialogs and DialogControls, which are always started from some code,
  27. &apos;&apos;&apos; Forms and FormControls will be initiated most often by the user, even if the SFDocuments library
  28. &apos;&apos;&apos; allows to start forms programmatically
  29. &apos;&apos;&apos;
  30. &apos;&apos;&apos; For Forms started programmatically, the corresponding objects are built top-down
  31. &apos;&apos;&apos; Event management of forms and their controls requires to being able to rebuild Form
  32. &apos;&apos;&apos; and FormControl objects bottom-up
  33. &apos;&apos;&apos;
  34. &apos;&apos;&apos; To avoid multiple rebuilds requested by multiple events,
  35. &apos;&apos;&apos; 1. The active form objects are cached in a global array of _FormCache types
  36. &apos;&apos;&apos; 2. FormControl objects are cached in Form objects
  37. &apos;&apos;&apos; 3. The bottom-up rebuild is executed only once, at instance creation
  38. Type _FormCache
  39. Terminated As Boolean
  40. XUnoForm As Object
  41. BasicForm As Object
  42. End Type
  43. REM ============================================================== PUBLIC METHODS
  44. REM -----------------------------------------------------------------------------
  45. Public Sub RegisterScriptServices() As Variant
  46. &apos;&apos;&apos; Register into ScriptForge the list of the services implemented by the current library
  47. &apos;&apos;&apos; Each library pertaining to the framework must implement its own version of this method
  48. &apos;&apos;&apos;
  49. &apos;&apos;&apos; It consists in successive calls to the RegisterService() and RegisterEventManager() methods
  50. &apos;&apos;&apos; with 2 arguments:
  51. &apos;&apos;&apos; ServiceName: the name of the service as a case-insensitive string
  52. &apos;&apos;&apos; ServiceReference: the reference as an object
  53. &apos;&apos;&apos; If the reference refers to a module, then return the module as an object:
  54. &apos;&apos;&apos; GlobalScope.Library.Module
  55. &apos;&apos;&apos; If the reference is a class instance, then return a string referring to the method
  56. &apos;&apos;&apos; containing the New statement creating the instance
  57. &apos;&apos;&apos; &quot;libraryname.modulename.function&quot;
  58. With GlobalScope.ScriptForge.SF_Services
  59. .RegisterService(&quot;Document&quot;, &quot;SFDocuments.SF_Register._NewDocument&quot;) &apos; Reference to the function initializing the service
  60. .RegisterService(&quot;Base&quot;, &quot;SFDocuments.SF_Register._NewDocument&quot;) &apos; Same reference, distinction is made inside the function
  61. .RegisterService(&quot;Calc&quot;, &quot;SFDocuments.SF_Register._NewDocument&quot;) &apos; Same reference, distinction is made inside the function
  62. .RegisterService(&quot;Writer&quot;, &quot;SFDocuments.SF_Register._NewDocument&quot;) &apos; Same reference, distinction is made inside the function
  63. .RegisterEventManager(&quot;DocumentEvent&quot;, &quot;SFDocuments.SF_Register._EventManager&quot;) &apos; Reference to the events manager
  64. .RegisterEventManager(&quot;FormEvent&quot;, &quot;SFDocuments.SF_Register._FormEventManager&quot;)&apos; Reference to the form and controls events manager
  65. End With
  66. End Sub &apos; SFDocuments.SF_Register.RegisterScriptServices
  67. REM =========================================================== PRIVATE FUNCTIONS
  68. REM -----------------------------------------------------------------------------
  69. Private Function _AddFormToCache(ByRef pvUnoForm As Object _
  70. , ByRef pvBasicForm As Object _
  71. ) As Long
  72. &apos;&apos;&apos; Add a new entry in the cache array with the references of the actual Form
  73. &apos;&apos;&apos; If relevant, the last entry of the cache is reused.
  74. &apos;&apos;&apos; The cache is located in the global _SF_ variable
  75. &apos;&apos;&apos; Args:
  76. &apos;&apos;&apos; pvUnoForm: com.sun.star.form.XForm or com.sun.star.comp.forms.ODatabaseForm
  77. &apos;&apos;&apos; pvBasicForm: its corresponding Basic object
  78. &apos;&apos;&apos; Returns:
  79. &apos;&apos;&apos; The index of the new or modified entry
  80. Dim vCache As New _FormCache &apos; Entry to be added
  81. Dim lIndex As Long &apos; UBound of _SF_.SFForms
  82. Dim vCacheArray As Variant &apos; Alias of _SF_.SFForms
  83. Try:
  84. vCacheArray = _SF_.SFForms
  85. If IsEmpty(vCacheArray) Then vCacheArray = Array()
  86. lIndex = UBound(vCacheArray)
  87. If lIndex &lt; LBound(vCacheArray) Then
  88. ReDim vCacheArray(0 To 0)
  89. lIndex = 0
  90. ElseIf Not vCacheArray(lIndex).Terminated Then &apos; Often last entry can be reused
  91. lIndex = lIndex + 1
  92. ReDim Preserve vCacheArray(0 To lIndex)
  93. End If
  94. With vCache
  95. .Terminated = False
  96. Set .XUnoForm = pvUnoForm
  97. Set .BasicForm = pvBasicForm
  98. End With
  99. Set vCacheArray(lIndex) = vCache
  100. _SF_.SFForms = vCacheArray
  101. Finally:
  102. _AddFormToCache = lIndex
  103. Exit Function
  104. End Function &apos; SFDocuments.SF_Register._AddFormToCache
  105. REM -----------------------------------------------------------------------------
  106. Private Sub _CleanCacheEntry(ByVal plIndex As Long)
  107. &apos;&apos;&apos; Clean the plIndex-th entry in the Forms cache
  108. &apos;&apos;&apos; Args:
  109. &apos;&apos;&apos; plIndex: must fit within the actual boundaries of the cache, otherwise the request is ignored
  110. Dim vCache As New _FormCache &apos; Cleaned entry
  111. With _SF_
  112. If Not IsArray(.SFForms) Then Exit Sub
  113. If plIndex &lt; LBound(.SFForms) Or plIndex &gt; UBound(.SFForms) Then Exit Sub
  114. With vCache
  115. .Terminated = True
  116. Set .XUnoForm = Nothing
  117. Set .BasicForm = Nothing
  118. End With
  119. .SFForms(plIndex) = vCache
  120. End With
  121. Finally:
  122. Exit Sub
  123. End Sub &apos; SFDocuments.SF_Register._CleanCacheEntry
  124. REM -----------------------------------------------------------------------------
  125. Public Function _EventManager(Optional ByRef pvArgs As Variant) As Object
  126. &apos;&apos;&apos; Returns a Document, Calc or Base object corresponding with the active component
  127. &apos;&apos;&apos; which triggered the event in argument
  128. &apos;&apos;&apos; This method should be triggered only thru the invocation of CreateScriptService
  129. &apos;&apos;&apos; Args:
  130. &apos;&apos;&apos; pvEvent: com.sun.star.document.DocumentEvent
  131. &apos;&apos;&apos; Returns:
  132. &apos;&apos;&apos; the output of a Document, Calc, ... service or Nothing
  133. &apos;&apos;&apos; Example:
  134. &apos;&apos;&apos; Sub TriggeredByEvent(ByRef poEvent As Object)
  135. &apos;&apos;&apos; Dim oDoc As Object
  136. &apos;&apos;&apos; Set oDoc = CreateScriptService(&quot;SFDocuments.DocumentEvent&quot;, poEvent)
  137. &apos;&apos;&apos; If Not IsNull(oDoc) Then
  138. &apos;&apos;&apos; &apos; ... (a valid document has been identified)
  139. &apos;&apos;&apos; End Sub
  140. Dim oSource As Object &apos; Return value
  141. Dim vEvent As Variant &apos; Alias of pvArgs(0)
  142. &apos; Never abort while an event is processed
  143. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Finally
  144. Set oSource = Nothing
  145. Check:
  146. If IsMissing(pvArgs) Or IsEmpty(pvArgs) Then pvArgs = Array()
  147. If UBound(pvArgs) &gt;= 0 Then vEvent = pvArgs(0) Else Set vEvent = Empty
  148. If VarType(vEvent) &lt;&gt; ScriptForge.V_OBJECT Then GoTo Finally
  149. Try:
  150. If ScriptForge.SF_Session.UnoObjectType(vEvent) = &quot;com.sun.star.document.DocumentEvent&quot; Then
  151. Set oSource = SF_Register._NewDocument(vEvent.Source)
  152. End If
  153. Finally:
  154. Set _EventManager = oSource
  155. Exit Function
  156. End Function &apos; SFDocuments.SF_Register._EventManager
  157. REM -----------------------------------------------------------------------------
  158. Private Function _FindFormInCache(ByRef poForm As Object) As Object
  159. &apos;&apos;&apos; Find the Form based on its XUnoForm
  160. &apos;&apos;&apos; The Form must not be terminated
  161. &apos;&apos;&apos; Returns:
  162. &apos;&apos;&apos; The corresponding Basic Form part or Nothing
  163. Dim oBasicForm As Object &apos; Return value
  164. Dim oCache As _FormCache &apos; Entry in the cache
  165. Set oBasicForm = Nothing
  166. Try:
  167. With _SF_
  168. If Not IsEmpty(.SFForms) Then
  169. For Each oCache In .SFForms
  170. If EqualUnoObjects(poForm, oCache.XUnoForm) And Not oCache.Terminated Then
  171. Set oBasicForm = oCache.BasicForm
  172. Exit For
  173. End If
  174. Next oCache
  175. End If
  176. End With
  177. Finally:
  178. Set _FindFormInCache = oBasicForm
  179. Exit Function
  180. End Function &apos; SFDocuments.SF_Register._FindFormInCache
  181. REM -----------------------------------------------------------------------------
  182. Public Function _FormEventManager(Optional ByRef pvArgs As Variant) As Object
  183. &apos;&apos;&apos; Returns a Form or FormControl object corresponding with the form or control
  184. &apos;&apos;&apos; which triggered the event in argument
  185. &apos;&apos;&apos; This method should be triggered only thru the invocation of CreateScriptService
  186. &apos;&apos;&apos; Args:
  187. &apos;&apos;&apos; pvEvent: com.sun.star.lang.EventObject
  188. &apos;&apos;&apos; Returns:
  189. &apos;&apos;&apos; the output of a Form, FormControl service or Nothing
  190. &apos;&apos;&apos; Example:
  191. &apos;&apos;&apos; Sub TriggeredByEvent(ByRef poEvent As Object)
  192. &apos;&apos;&apos; Dim oForm As Object
  193. &apos;&apos;&apos; Set oForm = CreateScriptService(&quot;SFDocuments.FormEvent&quot;, poEvent)
  194. &apos;&apos;&apos; If Not IsNull(oForm) Then
  195. &apos;&apos;&apos; &apos; ... (a valid form or subform has been identified)
  196. &apos;&apos;&apos; End Sub
  197. Dim oSource As Object &apos; Return value
  198. Dim vEvent As Variant &apos; Alias of pvArgs(0)
  199. Dim oControlModel As Object &apos; com.sun.star.awt.XControlModel
  200. Dim oParent As Object &apos; com.sun.star.form.OGridControlModel or com.sun.star.comp.forms.ODatabaseForm
  201. Dim sParentType As String &apos; &quot;com.sun.star.form.OGridControlModel&quot; or &quot;com.sun.star.comp.forms.ODatabaseForm&quot;
  202. Dim oSFParent As Object &apos; The parent as a ScriptForge instance: SF_Form or SF_FormControl
  203. Dim oSFForm As Object &apos; The grand-parent SF_Form instance
  204. Dim oSession As Object : Set oSession = ScriptForge.SF_Session
  205. &apos; Never abort while an event is processed
  206. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Finally
  207. Set oSource = Nothing
  208. Check:
  209. If IsMissing(pvArgs) Or IsEmpty(pvArgs) Then pvArgs = Array()
  210. If UBound(pvArgs) &gt;= 0 Then vEvent = pvArgs(0) Else Set vEvent = Empty
  211. If VarType(vEvent) &lt;&gt; ScriptForge.V_OBJECT Then GoTo Finally
  212. Try:
  213. If oSession.HasUnoProperty(vEvent, &quot;Source&quot;) Then
  214. &apos; FORM EVENT
  215. If oSession.UnoObjectType(vEvent.Source) = &quot;com.sun.star.comp.forms.ODatabaseForm&quot; Then
  216. Set oSource = SF_Register._NewForm(vEvent.Source, pbForceInit := True)
  217. &apos; CONTROL EVENT
  218. Else
  219. &apos; A SF_FormControl instance is always created from its parent, either a form, a subform or a table control
  220. Set oControlModel = vEvent.Source.Model &apos; The event source is a control view com.sun.star.awt.XControl
  221. Set oParent = oControlModel.Parent
  222. sParentType = oSession.UnoObjectType(oParent)
  223. Select Case sParentType
  224. Case &quot;com.sun.star.form.OGridControlModel&quot;
  225. Set oSFForm = SF_Register._NewForm(oParent.Parent, pbForceInit := True)
  226. Set oSFParent = oSFForm.Controls(oParent.Name)
  227. Case &quot;com.sun.star.comp.forms.ODatabaseForm&quot;
  228. Set oSFParent = SF_Register._NewForm(oParent, pbForceInit := True)
  229. End Select
  230. &apos; The final instance is derived from its parent instance
  231. Set oSource = oSFParent.Controls(oControlModel.Name)
  232. End If
  233. End If
  234. Finally:
  235. Set _FormEventManager = oSource
  236. Exit Function
  237. End Function &apos; SFDocuments.SF_Register._FormEventManager
  238. REM -----------------------------------------------------------------------------
  239. Public Function _GetEventScriptCode(poObject As Object _
  240. , ByVal psEvent As String _
  241. , ByVal psName As String _
  242. ) As String
  243. &apos;&apos;&apos; Extract from the parent of poObject the Basic script linked to psEvent.
  244. &apos;&apos;&apos; Helper function common to forms and form controls
  245. &apos;&apos;&apos; Args:
  246. &apos;&apos;&apos; poObject: a com.sun.star.form.XForm or XControl object
  247. &apos;&apos;&apos; psEvent: the &quot;On...&quot; name of the event
  248. &apos;&apos;&apos; psName: the name of the object to be identified from the parent object
  249. &apos;&apos;&apos; Returns:
  250. &apos;&apos;&apos; The script to trigger when psEvent occurs
  251. &apos;&apos;&apos; See Scripting Framework URI Specification : https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification
  252. Dim vEvents As Variant &apos; List of available events in the parent object
  253. &apos; Array of com.sun.star.script.ScriptEventDescriptor
  254. Dim sEvent As String &apos; The targeted event name
  255. Dim oParent As Object &apos; The parent object
  256. Dim lIndex As Long &apos; The index of the targeted event in the events list of the parent object
  257. Dim sName As String &apos; The corrected UNO event name
  258. Dim i As Long
  259. _GetEventScriptCode = &quot;&quot;
  260. On Local Error GoTo Catch
  261. If Not ScriptForge.SF_Session.HasUnoMethod(poObject, &quot;getParent&quot;) Then GoTo Finally
  262. Try:
  263. &apos; Find form index i.e. find control via getByIndex()
  264. &apos; The name is known (= psName) but getByIndex() is not in the same sequence as getElementNames()
  265. Set oParent = poObject.getParent()
  266. lIndex = -1
  267. For i = 0 To oParent.getCount() - 1
  268. sName = oParent.getByIndex(i).Name
  269. If (sName = psName) Then
  270. lIndex = i
  271. Exit For
  272. End If
  273. Next i
  274. If lIndex &lt; 0 Then GoTo Finally &apos; Not found, should not happen
  275. &apos; Find script triggered by event
  276. vEvents = oParent.getScriptEvents(lIndex) &apos; Returns an array
  277. &apos; Fix historical typo error
  278. sEvent = Replace(LCase(Mid(psEvent, 3, 1)) &amp; Mid(psEvent, 4), &quot;errorOccurred&quot;, &quot;errorOccured&quot;)
  279. For i = 0 To UBound(vEvents)
  280. If vEvents(i).EventMethod = sEvent Then
  281. _GetEventScriptCode = vEvents(i).ScriptCode
  282. Exit For
  283. End If
  284. Next i
  285. Finally:
  286. Exit Function
  287. Catch:
  288. GoTo Finally
  289. End Function &apos; SFDocuments.SF_Register._GetEventScriptCode
  290. REM -----------------------------------------------------------------------------
  291. Public Function _NewDocument(Optional ByVal pvArgs As Variant) As Object
  292. &apos;&apos;&apos; Create a new instance of the (super) SF_Document class or of one of its subclasses (SF_Calc, ...)
  293. &apos; Args:
  294. &apos;&apos;&apos; WindowName: see the definition of WindowName in the description of the UI service
  295. &apos;&apos;&apos; If absent, the document is presumed to be in the active window
  296. &apos;&apos;&apos; If WindowName is an object, it must be a component
  297. &apos;&apos;&apos; (com.sun.star.lang.XComponent or com.sun.star.comp.dba.ODatabaseDocument)
  298. &apos;&apos;&apos; Returns: the instance or Nothing
  299. Dim oDocument As Object &apos; Return value
  300. Dim oSuperDocument As Object &apos; Companion superclass document
  301. Dim vWindowName As Variant &apos; Alias of pvArgs(0)
  302. Dim oEnum As Object &apos; com.sun.star.container.XEnumeration
  303. Dim oComp As Object &apos; com.sun.star.lang.XComponent
  304. Dim vWindow As Window &apos; A single component
  305. Dim oUi As Object &apos; &quot;UI&quot; service
  306. Dim bFound As Boolean &apos; True if the document is found on the desktop
  307. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  308. Check:
  309. If IsMissing(pvArgs) Or IsEmpty(pvArgs) Then pvArgs = Array()
  310. If Not IsArray(pvArgs) Then pvArgs = Array(pvArgs) &apos; Needed when _NewDocument called from _EventManager
  311. If UBound(pvArgs) &gt;= 0 Then vWindowName = pvArgs(0) Else vWindowName = &quot;&quot;
  312. If Not ScriptForge.SF_Utils._Validate(vWindowName, &quot;WindowName&quot;, Array(V_STRING, ScriptForge.V_OBJECT)) Then GoTo Finally
  313. Set oDocument = Nothing
  314. Try:
  315. Set oUi = ScriptForge.SF_Services.CreateScriptService(&quot;UI&quot;)
  316. Select Case VarType(vWindowName)
  317. Case V_STRING
  318. If Len(vWindowName) &gt; 0 Then
  319. bFound = False
  320. Set oEnum = StarDesktop.Components().createEnumeration
  321. Do While oEnum.hasMoreElements
  322. Set oComp = oEnum.nextElement
  323. vWindow = oUi._IdentifyWindow(oComp)
  324. With vWindow
  325. &apos; Does the current window match the argument ?
  326. If (Len(.WindowFileName) &gt; 0 And .WindowFileName = ScriptForge.SF_FileSystem._ConvertToUrl(vWindowName)) _
  327. Or (Len(.WindowName) &gt; 0 And .WindowName = vWindowName) _
  328. Or (Len(.WindowTitle) &gt; 0 And .WindowTitle = vWindowName) Then
  329. bFound = True
  330. Exit Do
  331. End If
  332. End With
  333. Loop
  334. Else
  335. bFound = True
  336. vWindow = oUi._IdentifyWindow(StarDesktop.CurrentComponent)
  337. End If
  338. Case ScriptForge.V_OBJECT &apos; com.sun.star.lang.XComponent
  339. bFound = True
  340. vWindow = oUi._IdentifyWindow(vWindowName)
  341. End Select
  342. If bFound And Not IsNull(vWindow.Frame) And Len(vWindow.DocumentType) &gt; 0 Then
  343. &apos; Create the right subclass and associate to it a new instance of the superclass
  344. Select Case vWindow.DocumentType
  345. Case &quot;Base&quot;
  346. Set oDocument = New SF_Base
  347. Set oSuperDocument = New SF_Document
  348. Set oDocument.[_Super] = oSuperDocument &apos; Now both super and subclass are twinned
  349. Set oSuperDocument.[_SubClass] = oDocument
  350. Case &quot;Calc&quot;
  351. Set oDocument = New SF_Calc
  352. Set oSuperDocument = New SF_Document
  353. Set oDocument.[_Super] = oSuperDocument &apos; Now both super and subclass are twinned
  354. Set oSuperDocument.[_SubClass] = oDocument
  355. Case &quot;Writer&quot;
  356. Set oDocument = New SF_Writer
  357. Set oSuperDocument = New SF_Document
  358. Set oDocument.[_Super] = oSuperDocument &apos; Now both super and subclass are twinned
  359. Set oSuperDocument.[_SubClass] = oDocument
  360. Case Else &apos; Only superclass
  361. Set oDocument = New SF_Document
  362. Set oSuperDocument = oDocument
  363. End Select
  364. With oDocument &apos; Initialize attributes of subclass
  365. Set .[Me] = oDocument
  366. Set ._Component = vWindow.Component
  367. &apos; Initialize specific attributes
  368. Select Case vWindow.DocumentType
  369. Case &quot;Base&quot;
  370. Set ._DataSource = ._Component.DataSource
  371. Case Else
  372. End Select
  373. End With
  374. With oSuperDocument &apos; Initialize attributes of superclass
  375. Set .[Me] = oSuperDocument
  376. Set ._Component = vWindow.Component
  377. Set ._Frame = vWindow.Frame
  378. ._WindowName = vWindow.WindowName
  379. ._WindowTitle = vWindow.WindowTitle
  380. ._WindowFileName = vWindow.WindowFileName
  381. ._DocumentType = vWindow.DocumentType
  382. End With
  383. End If
  384. Finally:
  385. Set _NewDocument = oDocument
  386. Exit Function
  387. Catch:
  388. GoTo Finally
  389. End Function &apos; SFDocuments.SF_Register._NewDocument
  390. REM -----------------------------------------------------------------------------
  391. Public Function _NewForm(ByRef poForm As Object _
  392. , Optional pbForceInit As Boolean _
  393. ) As Object
  394. &apos;&apos;&apos; Returns an existing or a new SF_Form instance based on the argument
  395. &apos;&apos;&apos; If the instance is new (not found in cache), the minimal members are initialized
  396. &apos;&apos;&apos; Args:
  397. &apos;&apos;&apos; poForm: com.sun.star.form.XForm or com.sun.star.comp.forms.ODatabaseForm
  398. &apos;&apos;&apos; pbForceInit: when True, initialize the form instance. Default = False
  399. &apos;&apos;&apos; Returns:
  400. &apos;&apos;&apos; A SF_Form instance
  401. Dim oForm As Object &apos; Return value
  402. Try:
  403. Set oForm = SF_Register._FindFormInCache(poForm)
  404. If IsNull(oForm) Then &apos; Not found
  405. If IsMissing(pbForceInit) Or IsEmpty(pbForceInit) Then pbForceInit = False
  406. Set oForm = New SF_Form
  407. With oForm
  408. ._Name = poForm.Name
  409. Set .[Me] = oForm
  410. Set ._Form = poForm
  411. If pbForceInit Then ._Initialize()
  412. End With
  413. End If
  414. Finally:
  415. Set _NewForm = oForm
  416. Exit Function
  417. End Function &apos; SFDocuments.SF_Register._NewForm
  418. REM -----------------------------------------------------------------------------
  419. Public Function _RegisterEventScript(poObject As Object _
  420. , ByVal psEvent As String _
  421. , ByVal psListener As String _
  422. , ByVal psScriptCode As String _
  423. , ByVal psName As String _
  424. ) As Boolean
  425. &apos;&apos;&apos; Register a script event (psEvent) to poObject (Form, SubForm or Control)
  426. &apos;&apos;&apos; Args:
  427. &apos;&apos;&apos; poObject: a com.sun.star.form.XForm or XControl object
  428. &apos;&apos;&apos; psEvent: the &quot;On...&quot; name of the event
  429. &apos;&apos;&apos; psListener: the listener name corresponding with the event
  430. &apos;&apos;&apos; psScriptCode: The script to trigger when psEvent occurs
  431. &apos;&apos;&apos; See Scripting Framework URI Specification : https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification
  432. &apos;&apos;&apos; psName: the name of the object to associate with the event
  433. &apos;&apos;&apos; Returns:
  434. &apos;&apos;&apos; True when successful
  435. Dim oEvent As Object &apos; com.sun.star.script.ScriptEventDescriptor
  436. Dim sEvent As String &apos; The targeted event name
  437. Dim oParent As Object &apos; The parent object
  438. Dim lIndex As Long &apos; The index of the targeted event in the events list of the parent object
  439. Dim sName As String &apos; The corrected UNO event name
  440. Dim i As Long
  441. _RegisterEventScript = False
  442. On Local Error GoTo Catch
  443. If Not ScriptForge.SF_Session.HasUnoMethod(poObject, &quot;getParent&quot;) Then GoTo Finally
  444. Try:
  445. &apos; Find object&apos;s internal index i.e. how to reach it via getByIndex()
  446. Set oParent = poObject.getParent()
  447. lIndex = -1
  448. For i = 0 To oParent.getCount() - 1
  449. sName = oParent.getByIndex(i).Name
  450. If (sName = psName) Then
  451. lIndex = i
  452. Exit For
  453. End If
  454. Next i
  455. If lIndex &lt; 0 Then GoTo Finally &apos; Not found, should not happen
  456. &apos; Fix historical typo error
  457. sEvent = Replace(LCase(Mid(psEvent, 3, 1)) &amp; Mid(psEvent, 4), &quot;errorOccurred&quot;, &quot;errorOccured&quot;)
  458. &apos; Apply new script code. Erasing it is done with a specific UNO method
  459. If psScriptCode = &quot;&quot; Then
  460. oParent.revokeScriptEvent(lIndex, psListener, sEvent, &quot;&quot;)
  461. Else
  462. Set oEvent = CreateUnoStruct(&quot;com.sun.star.script.ScriptEventDescriptor&quot;)
  463. With oEvent
  464. .ListenerType = psListener
  465. .EventMethod = sEvent
  466. .ScriptType = &quot;Script&quot; &apos; Better than &quot;Basic&quot;
  467. .ScriptCode = psScriptCode
  468. End With
  469. oParent.registerScriptEvent(lIndex, oEvent)
  470. End If
  471. _RegisterEventScript = True
  472. Finally:
  473. Exit Function
  474. Catch:
  475. GoTo Finally
  476. End Function &apos; SFDocuments.SF_Register._RegisterEventScript
  477. REM ============================================== END OF SFDOCUMENTS.SF_REGISTER
  478. </script:module>