SF_Menu.xba 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  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_Menu" 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 SFWidgets 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 ClassModule
  10. Option Explicit
  11. &apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
  12. &apos;&apos;&apos; SF_Menu
  13. &apos;&apos;&apos; ============
  14. &apos;&apos;&apos; Display a menu in the menubar of a document or a form document.
  15. &apos;&apos;&apos; After use, the menu will not be saved neither in the application settings, nor in the document.
  16. &apos;&apos;&apos;
  17. &apos;&apos;&apos; The menu will be displayed, as usual, when its header in the menubar is clicked.
  18. &apos;&apos;&apos; When one of its items is selected, there are 3 alternative options:
  19. &apos;&apos;&apos; - a UNO command (like &quot;.uno:About&quot;) is triggered
  20. &apos;&apos;&apos; - a user script is run receiving a standard argument defined in this service
  21. &apos;&apos;&apos; - one of above combined with a toggle of the status of the item
  22. &apos;&apos;&apos;
  23. &apos;&apos;&apos; The menu is described from top to bottom. Each menu item receives a numeric and a string identifier.
  24. &apos;&apos;&apos;
  25. &apos;&apos;&apos; Menu items are either:
  26. &apos;&apos;&apos; - usual items
  27. &apos;&apos;&apos; - checkboxes
  28. &apos;&apos;&apos; - radio buttons
  29. &apos;&apos;&apos; - a menu separator
  30. &apos;&apos;&apos; Menu items can be decorated with icons and tooltips.
  31. &apos;&apos;&apos;
  32. &apos;&apos;&apos; Definitions:
  33. &apos;&apos;&apos; SubmenuCharacter: the character or the character string that identifies how menus are cascading
  34. &apos;&apos;&apos; Default = &quot;&gt;&quot;
  35. &apos;&apos;&apos; Can be set when invoking the Menu service
  36. &apos;&apos;&apos; ShortcutCharacter: the underline access key character
  37. &apos;&apos;&apos; Default = &quot;~&quot;
  38. &apos;&apos;&apos;
  39. &apos;&apos;&apos; Menus and submenus
  40. &apos;&apos;&apos; To create a menu with submenus, use the character defined in the
  41. &apos;&apos;&apos; SubmenuCharacter property while creating the menu entry to define where it will be
  42. &apos;&apos;&apos; placed. For instance, consider the following menu/submenu hierarchy.
  43. &apos;&apos;&apos; Item A
  44. &apos;&apos;&apos; Item B &gt; Item B.1
  45. &apos;&apos;&apos; Item B.2
  46. &apos;&apos;&apos; ------ (line separator)
  47. &apos;&apos;&apos; Item C &gt; Item C.1 &gt; Item C.1.1
  48. &apos;&apos;&apos; Item C.1.2
  49. &apos;&apos;&apos; Item C &gt; Item C.2 &gt; Item C.2.1
  50. &apos;&apos;&apos; Item C.2.2
  51. &apos;&apos;&apos; Next code will create the menu/submenu hierarchy
  52. &apos;&apos;&apos; With myMenu
  53. &apos;&apos;&apos; .AddItem(&quot;Item A&quot;)
  54. &apos;&apos;&apos; .AddItem(&quot;Item B&gt;Item B.1&quot;)
  55. &apos;&apos;&apos; .AddItem(&quot;Item B&gt;Item B.2&quot;)
  56. &apos;&apos;&apos; .AddItem(&quot;---&quot;)
  57. &apos;&apos;&apos; .AddItem(&quot;Item C&gt;Item C.1&gt;Item C.1.1&quot;)
  58. &apos;&apos;&apos; .AddItem(&quot;Item C&gt;Item C.1&gt;Item C.1.2&quot;)
  59. &apos;&apos;&apos; .AddItem(&quot;Item C&gt;Item C.2&gt;Item C.2.1&quot;)
  60. &apos;&apos;&apos; .AddItem(&quot;Item C&gt;Item C.2&gt;Item C.2.2&quot;)
  61. &apos;&apos;&apos; End With
  62. &apos;&apos;&apos;
  63. &apos;&apos;&apos; Service invocation:
  64. &apos;&apos;&apos; Dim ui As Object, oDoc As Object, myMenu As Object
  65. &apos;&apos;&apos; Set ui = CreateScriptService(&quot;UI&quot;)
  66. &apos;&apos;&apos; Set oDoc = ui.GetDocument(ThisComponent)
  67. &apos;&apos;&apos; Set myMenu = oDoc.CreateMenu(&quot;My own menu&quot;)
  68. &apos;&apos;&apos;
  69. &apos;&apos;&apos; Detailed user documentation:
  70. &apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/SF_Menu.html?DbPAR=BASIC
  71. &apos;&apos;&apos;
  72. &apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
  73. REM ================================================================== EXCEPTIONS
  74. REM ============================================================= PRIVATE MEMBERS
  75. Private [Me] As Object
  76. Private ObjectType As String &apos; Must be MENU
  77. Private ServiceName As String
  78. &apos; Menu descriptors
  79. Private Component As Object &apos; the com.sun.star.lang.XComponent hosting the menu in its menubar
  80. Private MenuBar As Object &apos; com.sun.star.awt.XMenuBar or stardiv.Toolkit.VCLXMenuBar
  81. Private SubmenuChar As String &apos; Delimiter in menu trees
  82. Private MenuHeader As String &apos; Header of the menu
  83. Private MenuId As Integer &apos; Menu numeric identifier in the menubar
  84. Private MenuPosition As Integer &apos; Position of the menu on the menubar &gt;= 1
  85. Private PopupMenu As Object &apos; The underlying popup menu as a SF_PopupMenu object
  86. REM ============================================================ MODULE CONSTANTS
  87. Private Const _UnderlineAccessKeyChar = &quot;~&quot;
  88. Private Const _DefaultSubmenuChar = &quot;&gt;&quot;
  89. Private Const cstUnoPrefix = &quot;.uno:&quot;
  90. Private Const cstScriptArg = &quot;:::&quot;
  91. Private Const cstNormal = &quot;N&quot;
  92. Private Const cstCheck = &quot;C&quot;
  93. Private Const cstRadio = &quot;R&quot;
  94. REM ====================================================== CONSTRUCTOR/DESTRUCTOR
  95. REM -----------------------------------------------------------------------------
  96. Private Sub Class_Initialize()
  97. Set [Me] = Nothing
  98. ObjectType = &quot;MENU&quot;
  99. ServiceName = &quot;SFWidgets.Menu&quot;
  100. Set Component = Nothing
  101. Set MenuBar = Nothing
  102. SubmenuChar = _DefaultSubmenuChar
  103. MenuHeader = &quot;&quot;
  104. MenuId = -1
  105. MenuPosition = 0
  106. Set PopupMenu = Nothing
  107. End Sub &apos; SFWidgets.SF_Menu Constructor
  108. REM -----------------------------------------------------------------------------
  109. Private Sub Class_Terminate()
  110. Call Class_Initialize()
  111. End Sub &apos; SFWidgets.SF_Menu Destructor
  112. REM -----------------------------------------------------------------------------
  113. Public Function Dispose() As Variant
  114. PopupMenu.Dispose()
  115. Call Class_Terminate()
  116. Set Dispose = Nothing
  117. End Function &apos; SFWidgets.SF_Menu Explicit Destructor
  118. REM ================================================================== PROPERTIES
  119. REM -----------------------------------------------------------------------------
  120. Property Get ShortcutCharacter() As Variant
  121. &apos;&apos;&apos; The ShortcutCharacter property specifies character preceding the underline access key
  122. ShortcutCharacter = _PropertyGet(&quot;ShortcutCharacter&quot;)
  123. End Property &apos; SFWidgets.SF_Menu.ShortcutCharacter (get)
  124. REM -----------------------------------------------------------------------------
  125. Property Get SubmenuCharacter() As Variant
  126. &apos;&apos;&apos; The SubmenuCharacter property specifies the character string indicating
  127. &apos;&apos;&apos; a sub-menu in a popup menu item
  128. SubmenuCharacter = _PropertyGet(&quot;SubmenuCharacter&quot;)
  129. End Property &apos; SFWidgets.SF_Menu.SubmenuCharacter (get)
  130. REM ===================================================================== METHODS
  131. REM -----------------------------------------------------------------------------
  132. Public Function AddCheckBox(Optional ByVal MenuItem As Variant _
  133. , Optional ByVal Name As Variant _
  134. , Optional ByVal Status As Variant _
  135. , Optional ByVal Icon As Variant _
  136. , Optional ByVal Tooltip As Variant _
  137. , Optional ByVal Command As Variant _
  138. , Optional ByVal Script As Variant _
  139. ) As Integer
  140. &apos;&apos;&apos; Insert in the popup menu a new entry as a checkbox
  141. &apos;&apos;&apos; Args:
  142. &apos;&apos;&apos; MenuItem: The text to be displayed in the menu entry.
  143. &apos;&apos;&apos; It determines also the hierarchy of the popup menu
  144. &apos;&apos;&apos; It is made up of all the components (separated by the &quot;SubmenuCharacter&quot;) of the menu branch
  145. &apos;&apos;&apos; Example: A&gt;B&gt;C means &quot;C&quot; is a new entry in submenu &quot;A =&gt; B =&gt;&quot;
  146. &apos;&apos;&apos; If the last component is equal to the &quot;SeparatorCharacter&quot;, a line separator is inserted
  147. &apos;&apos;&apos; Name: The name identifying the item. Default = the last component of MenuItem.
  148. &apos;&apos;&apos; Status: when True the item is selected. Default = False
  149. &apos;&apos;&apos; Icon: The path name of the icon to be displayed, without leading path separator
  150. &apos;&apos;&apos; The icons are stored in one of the &lt;install folder&gt;/share/config/images_*.zip files
  151. &apos;&apos;&apos; The exact file depends on the user options about the current icon set
  152. &apos;&apos;&apos; Use the (normal) slash &quot;/&quot; as path separator
  153. &apos;&apos;&apos; Example: &quot;cmd/sc_cut.png&quot;
  154. &apos;&apos;&apos; Tooltip: The help text to be displayed as a tooltip
  155. &apos;&apos;&apos; Command: A menu command like &quot;.uno:About&quot;. The validity of the command is not checked.
  156. &apos;&apos;&apos; Script: a Basic or Python script (determined by its URI notation) to be run when the item is clicked
  157. &apos;&apos;&apos; Read https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification
  158. &apos;&apos;&apos; Next string argument will be passed to the called script : a comma-separated string of 4 components:
  159. &apos;&apos;&apos; - the menu header
  160. &apos;&apos;&apos; - the name of the clicked menu item
  161. &apos;&apos;&apos; - the numeric identifier of the clicked menu item
  162. &apos;&apos;&apos; - &quot;1&quot; when the status is &quot;checked&quot;, otherwise &quot;0&quot;
  163. &apos;&apos;&apos; Arguments Command and Script are mutually exclusive.
  164. &apos;&apos;&apos; Returns:
  165. &apos;&apos;&apos; The numeric identification of the newly inserted item
  166. &apos;&apos;&apos; Examples:
  167. &apos;&apos;&apos; Dim iId As Integer
  168. &apos;&apos;&apos; iId = myMenu.AddCheckBox(&quot;Menu top&gt;Checkbox item&quot;, Status := True, Command := &quot;Bold&quot;)
  169. Dim iId As Integer &apos; Return value
  170. Dim sCommand As String &apos; Alias of either Command or Script
  171. Const cstThisSub = &quot;SFWidgets.Menu.AddCheckBox&quot;
  172. Const cstSubArgs = &quot;MenuItem, [Name=&quot;&quot;&quot;&quot;], [Status=False], [Icon=&quot;&quot;&quot;&quot;], [Tooltip=&quot;&quot;&quot;&quot;], [Command=&quot;&quot;&quot;&quot;], [Script=&quot;&quot;&quot;&quot;]&quot;
  173. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  174. iId = 0
  175. Check:
  176. If IsMissing(Name) Or IsEmpty(Name) Then Name = &quot;&quot;
  177. If IsMissing(Status) Or IsEmpty(Status) Then Status = False
  178. If IsMissing(Icon) Or IsEmpty(Icon) Then Icon = &quot;&quot;
  179. If IsMissing(Tooltip) Or IsEmpty(Tooltip) Then Tooltip = &quot;&quot;
  180. If IsMissing(Command) Or IsEmpty(Command) Then Command = &quot;&quot;
  181. If IsMissing(Script) Or IsEmpty(Script) Then Script = &quot;&quot;
  182. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  183. If Not ScriptForge.SF_Utils._Validate(MenuItem, &quot;MenuItem&quot;, V_STRING) Then GoTo Catch
  184. If Not ScriptForge.SF_Utils._Validate(Name, &quot;Name&quot;, V_STRING) Then GoTo Catch
  185. If Not ScriptForge.SF_Utils._Validate(Status, &quot;Status&quot;, ScriptForge.V_BOOLEAN) Then GoTo Catch
  186. If Not ScriptForge.SF_Utils._Validate(Icon, &quot;Icon&quot;, V_STRING) Then GoTo Catch
  187. If Not ScriptForge.SF_Utils._Validate(Tooltip, &quot;Tooltip&quot;, V_STRING) Then GoTo Catch
  188. If Not ScriptForge.SF_Utils._Validate(Command, &quot;Command&quot;, V_STRING) Then GoTo Catch
  189. If Not ScriptForge.SF_Utils._Validate(Script, &quot;Script&quot;, V_STRING) Then GoTo Catch
  190. End If
  191. If Len(Command) &gt; 0 Then
  192. If Left(Command, Len(cstUnoPrefix)) = cstUnoPrefix Then sCommand = Command Else sCommand = cstUnoPrefix &amp; Command
  193. Else
  194. sCommand = Script &amp; cstScriptArg &amp; MenuHeader
  195. End If
  196. Try:
  197. iId = PopupMenu._AddItem(MenuItem, Name, cstCheck, Status, Icon, Tooltip, sCommand)
  198. Finally:
  199. AddCheckBox = iId
  200. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  201. Exit Function
  202. Catch:
  203. GoTo Finally
  204. End Function &apos; SFWidgets.SF_Menu.AddCheckBox
  205. REM -----------------------------------------------------------------------------
  206. Public Function AddItem(Optional ByVal MenuItem As Variant _
  207. , Optional ByVal Name As Variant _
  208. , Optional ByVal Icon As Variant _
  209. , Optional ByVal Tooltip As Variant _
  210. , Optional ByVal Command As Variant _
  211. , Optional ByVal Script As Variant _
  212. ) As Integer
  213. &apos;&apos;&apos; Insert in the popup menu a new entry
  214. &apos;&apos;&apos; Args:
  215. &apos;&apos;&apos; MenuItem: The text to be displayed in the menu entry.
  216. &apos;&apos;&apos; It determines also the hierarchy of the popup menu
  217. &apos;&apos;&apos; It is made up of all the components (separated by the &quot;SubmenuCharacter&quot;) of the menu branch
  218. &apos;&apos;&apos; Example: A&gt;B&gt;C means &quot;C&quot; is a new entry in submenu &quot;A =&gt; B =&gt;&quot;
  219. &apos;&apos;&apos; If the last component is equal to &quot;---&quot;, a line separator is inserted and all other arguments are ignored
  220. &apos;&apos;&apos; Name: The name identifying the item. Default = the last component of MenuItem.
  221. &apos;&apos;&apos; Icon: The path name of the icon to be displayed, without leading path separator
  222. &apos;&apos;&apos; The icons are stored in one of the &lt;install folder&gt;/share/config/images_*.zip files
  223. &apos;&apos;&apos; The exact file depends on the user options about the current icon set
  224. &apos;&apos;&apos; Use the (normal) slash &quot;/&quot; as path separator
  225. &apos;&apos;&apos; Example: &quot;cmd/sc_cut.png&quot;
  226. &apos;&apos;&apos; Tooltip: The help text to be displayed as a tooltip
  227. &apos;&apos;&apos; Command: A menu command like &quot;.uno:About&quot;. The validity of the command is not checked.
  228. &apos;&apos;&apos; Script: a Basic or Python script (determined by its URI notation) to be run when the item is clicked
  229. &apos;&apos;&apos; Read https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification
  230. &apos;&apos;&apos; Next string argument will be passed to the called script : a comma-separated string of 4 components:
  231. &apos;&apos;&apos; - the menu header
  232. &apos;&apos;&apos; - the name of the clicked menu item
  233. &apos;&apos;&apos; - the numeric identifier of the clicked menu item
  234. &apos;&apos;&apos; - &quot;0&quot;
  235. &apos;&apos;&apos; Arguments Command and Script are mutually exclusive.
  236. &apos;&apos;&apos; Returns:
  237. &apos;&apos;&apos; The numeric identification of the newly inserted item
  238. &apos;&apos;&apos; Examples:
  239. &apos;&apos;&apos; Dim iId1 As Integer, iId2 As Integer
  240. &apos;&apos;&apos; iId1 = myMenu.AddItem(&quot;Menu top&gt;Normal item 1&quot;, Icon := &quot;cmd.sc_cut.png&quot;, Command := &quot;About&quot;)
  241. &apos;&apos;&apos; iId2 = myMenu.AddItem(&quot;Menu top&gt;Normal item 2&quot;, Script := &quot;vnd.sun.star.script:myLib.Module1.ThisSub?language=Basic&amp;location=document&quot;)
  242. Dim iId As Integer &apos; Return value
  243. Dim sCommand As String &apos; Alias of either Command or Script
  244. Const cstThisSub = &quot;SFWidgets.Menu.AddItem&quot;
  245. Const cstSubArgs = &quot;MenuItem, [Name=&quot;&quot;&quot;&quot;], [Icon=&quot;&quot;&quot;&quot;], [Tooltip=&quot;&quot;&quot;&quot;], [Command=&quot;&quot;&quot;&quot;], [Script=&quot;&quot;&quot;&quot;]&quot;
  246. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  247. iId = 0
  248. Check:
  249. If IsMissing(Name) Or IsEmpty(Name) Then Name = &quot;&quot;
  250. If IsMissing(Icon) Or IsEmpty(Icon) Then Icon = &quot;&quot;
  251. If IsMissing(Tooltip) Or IsEmpty(Tooltip) Then Tooltip = &quot;&quot;
  252. If IsMissing(Command) Or IsEmpty(Command) Then Command = &quot;&quot;
  253. If IsMissing(Script) Or IsEmpty(Script) Then Script = &quot;&quot;
  254. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  255. If Not ScriptForge.SF_Utils._Validate(MenuItem, &quot;MenuItem&quot;, V_STRING) Then GoTo Catch
  256. If Not ScriptForge.SF_Utils._Validate(Name, &quot;Name&quot;, V_STRING) Then GoTo Catch
  257. If Not ScriptForge.SF_Utils._Validate(Icon, &quot;Icon&quot;, V_STRING) Then GoTo Catch
  258. If Not ScriptForge.SF_Utils._Validate(Tooltip, &quot;Tooltip&quot;, V_STRING) Then GoTo Catch
  259. If Not ScriptForge.SF_Utils._Validate(Command, &quot;Command&quot;, V_STRING) Then GoTo Catch
  260. If Not ScriptForge.SF_Utils._Validate(Script, &quot;Script&quot;, V_STRING) Then GoTo Catch
  261. End If
  262. If Len(Command) &gt; 0 Then
  263. If Left(Command, Len(cstUnoPrefix)) = cstUnoPrefix Then sCommand = Command Else sCommand = cstUnoPrefix &amp; Command
  264. Else
  265. sCommand = Script &amp; cstScriptArg &amp; MenuHeader
  266. End If
  267. Try:
  268. iId = PopupMenu._AddItem(MenuItem, Name, cstNormal, False, Icon, Tooltip, sCommand)
  269. Finally:
  270. AddItem = iId
  271. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  272. Exit Function
  273. Catch:
  274. GoTo Finally
  275. End Function &apos; SFWidgets.SF_Menu.AddItem
  276. REM -----------------------------------------------------------------------------
  277. Public Function AddRadioButton(Optional ByVal MenuItem As Variant _
  278. , Optional ByVal Name As Variant _
  279. , Optional ByVal Status As Variant _
  280. , Optional ByVal Icon As Variant _
  281. , Optional ByVal Tooltip As Variant _
  282. , Optional ByVal Command As Variant _
  283. , Optional ByVal Script As Variant _
  284. ) As Integer
  285. &apos;&apos;&apos; Insert in the popup menu a new entry as a radio button
  286. &apos;&apos;&apos; Args:
  287. &apos;&apos;&apos; MenuItem: The text to be displayed in the menu entry.
  288. &apos;&apos;&apos; It determines also the hieAddCheckBoxrarchy of the popup menu
  289. &apos;&apos;&apos; It is made up of all the components (separated by the &quot;SubmenuCharacter&quot;) of the menu branch
  290. &apos;&apos;&apos; Example: A&gt;B&gt;C means &quot;C&quot; is a new entry in submenu &quot;A =&gt; B =&gt;&quot;
  291. &apos;&apos;&apos; If the last component is equal to the &quot;SeparatorCharacter&quot;, a line separator is inserted
  292. &apos;&apos;&apos; Name: The name identifying the item. Default = the last component of MenuItem.
  293. &apos;&apos;&apos; Status: when True the item is selected. Default = False
  294. &apos;&apos;&apos; Icon: The path name of the icon to be displayed, without leading path separator
  295. &apos;&apos;&apos; The icons are stored in one of the &lt;install folder&gt;/share/config/images_*.zip files
  296. &apos;&apos;&apos; The exact file depends on the user options about the current icon set
  297. &apos;&apos;&apos; Use the (normal) slash &quot;/&quot; as path separator
  298. &apos;&apos;&apos; Example: &quot;cmd/sc_cut.png&quot;
  299. &apos;&apos;&apos; Tooltip: The help text to be displayed as a tooltip
  300. &apos;&apos;&apos; Command: A menu command like &quot;.uno:About&quot;. The validity of the command is not checked.
  301. &apos;&apos;&apos; Script: a Basic or Python script (determined by its URI notation) to be run when the item is clicked
  302. &apos;&apos;&apos; Read https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification
  303. &apos;&apos;&apos; Next string argument will be passed to the called script : a comma-separated string of 4 components:
  304. &apos;&apos;&apos; - the menu header
  305. &apos;&apos;&apos; - the name of the clicked menu item
  306. &apos;&apos;&apos; - the numeric identifier of theclicked menu item
  307. &apos;&apos;&apos; - &quot;1&quot; when the status is &quot;checked&quot;, otherwise &quot;0&quot;
  308. &apos;&apos;&apos; Arguments Command and Script are mutually exclusive.
  309. &apos;&apos;&apos; Returns:
  310. &apos;&apos;&apos; The numeric identification of the newly inserted item
  311. &apos;&apos;&apos; Examples:
  312. &apos;&apos;&apos; Dim iId As Integer
  313. &apos;&apos;&apos; iId = myMenu.AddRadioButton(&quot;Menu top&gt;Radio item&quot;, Status := True, Command := &quot;Bold&quot;)
  314. Dim iId As Integer &apos; Return value
  315. Dim sCommand As String &apos; Alias of either Command or Script
  316. Const cstThisSub = &quot;SFWidgets.Menu.AddRadioButton&quot;
  317. Const cstSubArgs = &quot;MenuItem, [Name=&quot;&quot;&quot;&quot;], [Status=False], [Icon=&quot;&quot;&quot;&quot;], [Tooltip=&quot;&quot;&quot;&quot;], [Command=&quot;&quot;&quot;&quot;], [Script=&quot;&quot;&quot;&quot;]&quot;
  318. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  319. iId = 0
  320. Check:
  321. If IsMissing(Name) Or IsEmpty(Name) Then Name = &quot;&quot;
  322. If IsMissing(Status) Or IsEmpty(Status) Then Status = False
  323. If IsMissing(Icon) Or IsEmpty(Icon) Then Icon = &quot;&quot;
  324. If IsMissing(Tooltip) Or IsEmpty(Tooltip) Then Tooltip = &quot;&quot;
  325. If IsMissing(Command) Or IsEmpty(Command) Then Command = &quot;&quot;
  326. If IsMissing(Script) Or IsEmpty(Script) Then Script = &quot;&quot;
  327. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  328. If Not ScriptForge.SF_Utils._Validate(MenuItem, &quot;MenuItem&quot;, V_STRING) Then GoTo Catch
  329. If Not ScriptForge.SF_Utils._Validate(Name, &quot;Name&quot;, V_STRING) Then GoTo Catch
  330. If Not ScriptForge.SF_Utils._Validate(Status, &quot;Status&quot;, ScriptForge.V_BOOLEAN) Then GoTo Catch
  331. If Not ScriptForge.SF_Utils._Validate(Icon, &quot;Icon&quot;, V_STRING) Then GoTo Catch
  332. If Not ScriptForge.SF_Utils._Validate(Tooltip, &quot;Tooltip&quot;, V_STRING) Then GoTo Catch
  333. If Not ScriptForge.SF_Utils._Validate(Command, &quot;Command&quot;, V_STRING) Then GoTo Catch
  334. If Not ScriptForge.SF_Utils._Validate(Script, &quot;Script&quot;, V_STRING) Then GoTo Catch
  335. End If
  336. If Len(Command) &gt; 0 Then
  337. If Left(Command, Len(cstUnoPrefix)) = cstUnoPrefix Then sCommand = Command Else sCommand = cstUnoPrefix &amp; Command
  338. Else
  339. sCommand = Script &amp; cstScriptArg &amp; MenuHeader
  340. End If
  341. Try:
  342. iId = PopupMenu._AddItem(MenuItem, Name, cstRadio, Status, Icon, Tooltip, sCommand)
  343. Finally:
  344. AddRadioButton = iId
  345. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  346. Exit Function
  347. Catch:
  348. GoTo Finally
  349. End Function &apos; SFWidgets.SF_Menu.AddRadioButton
  350. REM -----------------------------------------------------------------------------
  351. Public Function GetProperty(Optional ByVal PropertyName As Variant) As Variant
  352. &apos;&apos;&apos; Return the actual value of the given property
  353. &apos;&apos;&apos; Args:
  354. &apos;&apos;&apos; PropertyName: the name of the property as a string
  355. &apos;&apos;&apos; Returns:
  356. &apos;&apos;&apos; The actual value of the property
  357. &apos;&apos;&apos; If the property does not exist, returns Null
  358. &apos;&apos;&apos; Exceptions:
  359. &apos;&apos;&apos; see the exceptions of the individual properties
  360. &apos;&apos;&apos; Examples:
  361. &apos;&apos;&apos; myModel.GetProperty(&quot;MyProperty&quot;)
  362. Const cstThisSub = &quot;SFWidgets.Menu.GetProperty&quot;
  363. Const cstSubArgs = &quot;&quot;
  364. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  365. GetProperty = Null
  366. Check:
  367. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  368. If Not ScriptForge.SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
  369. End If
  370. Try:
  371. GetProperty = _PropertyGet(PropertyName)
  372. Finally:
  373. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  374. Exit Function
  375. Catch:
  376. GoTo Finally
  377. End Function &apos; SFWidgets.SF_Menu.GetProperty
  378. REM -----------------------------------------------------------------------------
  379. Public Function Methods() As Variant
  380. &apos;&apos;&apos; Return the list of public methods of the Model service as an array
  381. Methods = Array( _
  382. &quot;AddCheckBox&quot; _
  383. , &quot;AddItem&quot; _
  384. , &quot;AddRadioButton&quot; _
  385. )
  386. End Function &apos; SFWidgets.SF_Menu.Methods
  387. REM -----------------------------------------------------------------------------
  388. Public Function Properties() As Variant
  389. &apos;&apos;&apos; Return the list or properties of the Timer a.AddItem(&quot;B&gt;B1&quot;)class as an array
  390. Properties = Array( _
  391. &quot;ShortcutCharacter&quot; _
  392. , &quot;SubmenuCharacter&quot; _
  393. )
  394. End Function &apos; SFWidgets.SF_Menu.Properties
  395. REM -----------------------------------------------------------------------------
  396. Public Function SetProperty(Optional ByVal PropertyName As Variant _
  397. , Optional ByRef Value As Variant _
  398. ) As Boolean
  399. &apos;&apos;&apos; Set a new value to the given property
  400. &apos;&apos;&apos; Args:
  401. &apos;&apos;&apos; PropertyName: the name of the property as a string
  402. &apos;&apos;&apos; Value: its new value
  403. &apos;&apos;&apos; Exceptions
  404. &apos;&apos;&apos; ARGUMENTERROR The property does not exist
  405. Const cstThisSub = &quot;SFWidgets.Menu.SetProperty&quot;
  406. Const cstSubArgs = &quot;PropertyName, Value&quot;
  407. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  408. SetProperty = False
  409. Check:
  410. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  411. If Not SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
  412. End If
  413. Try:
  414. SetProperty = _PropertySet(PropertyName, Value)
  415. Finally:
  416. SF_Utils._ExitFunction(cstThisSub)
  417. Exit Function
  418. Catch:
  419. GoTo Finally
  420. End Function &apos; SFWidgets.SF_Menu.SetProperty
  421. REM =========================================================== PRIVATE FUNCTIONS
  422. REM -----------------------------------------------------------------------------
  423. Public Sub _Initialize(ByRef poComponent As Object _
  424. , psMenuHeader As String _
  425. , psBefore As String _
  426. , piBefore As Integer _
  427. , psSubmenuChar As String _
  428. )
  429. &apos;&apos;&apos; Complete the object creation process:
  430. &apos;&apos;&apos; - Initialize the internal properties
  431. &apos;&apos;&apos; - Initialize the menubar
  432. &apos;&apos;&apos; - Determine the position and the internal id of the new menu
  433. &apos;&apos;&apos; - Create the menu and its attached popup menu
  434. &apos;&apos;&apos; Args:
  435. &apos;&apos;&apos; poComponent: the parent component where the menubar is to be searched for
  436. &apos;&apos;&apos; psMenuHeader: the header of the new menu. May or not contain a tilde &quot;~&quot;
  437. &apos;&apos;&apos; psBefore, piBefore: the menu before which to create the new menu, as a string or as a number
  438. &apos;&apos;&apos; psSubmenuChar: the submenus separator
  439. Dim oLayout As Object &apos; com.sun.star.comp.framework.LayoutManager
  440. Dim sName As String &apos; Menu name
  441. Dim iMenuId As Integer &apos; Menu identifier
  442. Dim oWindow As Object &apos; ui.Window type
  443. Dim oUi As Object : Set oUi = ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.UI&quot;)
  444. Dim i As Integer
  445. Const cstTilde = &quot;~&quot;
  446. Check:
  447. &apos; How does the window look on top of which a menu is requested ?
  448. Set oWindow = oUi._IdentifyWindow(poComponent)
  449. With oWindow
  450. If Not IsNull(.Frame) Then Set oLayout = .Frame.LayoutManager Else GoTo Finally
  451. End With
  452. Try:
  453. &apos; Initialize the menubar
  454. Set MenuBar = oLayout.getElement(&quot;private:resource/menubar/menubar&quot;).XMenuBar
  455. &apos; Determine the new menu identifier and its position
  456. &apos; Identifier = largest current identifier + 1
  457. MenuHeader = psMenuHeader
  458. With MenuBar
  459. For i = 0 To .ItemCount - 1
  460. iMenuId = .getItemId(i)
  461. If iMenuId &gt;= MenuId Then MenuId = iMenuId + 1
  462. If piBefore &gt; 0 And piBefore = i + 1 Then
  463. MenuPosition = piBefore
  464. Else
  465. sName = .getItemText(iMenuId)
  466. If sName = psBefore Or Replace(sName, cstTilde, &quot;&quot;) = psBefore Then MenuPosition = i + 1
  467. End If
  468. Next i
  469. If MenuPosition = 0 Then MenuPosition = .ItemCount + 1
  470. End With
  471. &apos; Store the submenu character
  472. If Len(psSubmenuChar) &gt; 0 Then SubmenuChar = psSubmenuChar
  473. &apos; Create the menu and the attached top popup menu
  474. MenuBar.insertItem(MenuId, MenuHeader, 0, MenuPosition - 1)
  475. PopupMenu = SFWidgets.SF_Register._NewPopupMenu(Array(Nothing, 0, 0, SubmenuChar))
  476. PopupMenu.MenubarMenu = True &apos; Special indicator for menus depending on menubar
  477. MenuBar.setPopupMenu(MenuId, PopupMenu.MenuRoot)
  478. &apos; Initialize the listener on the top branch
  479. SFWidgets.SF_MenuListener.SetMenuListener(PopupMenu.MenuRoot)
  480. Finally:
  481. Exit Sub
  482. End Sub &apos; SFWidgets.SF_Menu._Initialize
  483. REM -----------------------------------------------------------------------------
  484. Private Function _PropertyGet(Optional ByVal psProperty As String) As Variant
  485. &apos;&apos;&apos; Return the value of the named property
  486. &apos;&apos;&apos; Args:
  487. &apos;&apos;&apos; psProperty: the name of the property
  488. Dim vGet As Variant &apos; Return value
  489. Dim cstThisSub As String
  490. Const cstSubArgs = &quot;&quot;
  491. cstThisSub = &quot;SFWidgets.Menu.get&quot; &amp; psProperty
  492. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  493. ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
  494. _PropertyGet = Null
  495. Select Case UCase(psProperty)
  496. Case UCase(&quot;ShortcutCharacter&quot;)
  497. _PropertyGet = _UnderlineAccessKeyChar
  498. Case UCase(&quot;SubmenuCharacter&quot;)
  499. _PropertyGet = SubmenuChar
  500. Case Else
  501. _PropertyGet = Null
  502. End Select
  503. Finally:
  504. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  505. Exit Function
  506. Catch:
  507. GoTo Finally
  508. End Function &apos; SFWidgets.SF_Menu._PropertyGet
  509. REM -----------------------------------------------------------------------------
  510. Private Function _Repr() As String
  511. &apos;&apos;&apos; Convert the SF_Menu instance to a readable string, typically for debugging purposes (DebugPrint ...)
  512. &apos;&apos;&apos; Args:
  513. &apos;&apos;&apos; Return:
  514. &apos;&apos;&apos; &quot;[Menu]: Name, Type (dialogname)
  515. _Repr = &quot;[Menu]: &quot; &amp; SF_String.Represent(PopupMenu.MenuTree.Keys()) &amp; &quot;, &quot; &amp; SF_String.Represent(PopupMenu.MenuIdentification.Items())
  516. End Function &apos; SFWidgets.SF_Menu._Repr
  517. REM ============================================ END OF SFWIDGETS.SF_MENU
  518. </script:module>