summaryrefslogtreecommitdiffstats
path: root/wizards/source/sfwidgets
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /wizards/source/sfwidgets
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'wizards/source/sfwidgets')
-rw-r--r--wizards/source/sfwidgets/SF_Menu.xba598
-rw-r--r--wizards/source/sfwidgets/SF_MenuListener.xba131
-rw-r--r--wizards/source/sfwidgets/SF_PopupMenu.xba801
-rw-r--r--wizards/source/sfwidgets/SF_Register.xba257
-rw-r--r--wizards/source/sfwidgets/SF_Toolbar.xba541
-rw-r--r--wizards/source/sfwidgets/SF_ToolbarButton.xba565
-rw-r--r--wizards/source/sfwidgets/__License.xba26
-rw-r--r--wizards/source/sfwidgets/dialog.xlb3
-rw-r--r--wizards/source/sfwidgets/script.xlb11
9 files changed, 2933 insertions, 0 deletions
diff --git a/wizards/source/sfwidgets/SF_Menu.xba b/wizards/source/sfwidgets/SF_Menu.xba
new file mode 100644
index 0000000000..85d505904d
--- /dev/null
+++ b/wizards/source/sfwidgets/SF_Menu.xba
@@ -0,0 +1,598 @@
+<?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_Menu" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
+REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
+REM === The SFWidgets 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_Menu
+&apos;&apos;&apos; ============
+&apos;&apos;&apos; Display a menu in the menubar of a document or a form document.
+&apos;&apos;&apos; After use, the menu will not be saved neither in the application settings, nor in the document.
+&apos;&apos;&apos;
+&apos;&apos;&apos; The menu will be displayed, as usual, when its header in the menubar is clicked.
+&apos;&apos;&apos; When one of its items is selected, there are 3 alternative options:
+&apos;&apos;&apos; - a UNO command (like &quot;.uno:About&quot;) is triggered
+&apos;&apos;&apos; - a user script is run receiving a standard argument defined in this service
+&apos;&apos;&apos; - one of above combined with a toggle of the status of the item
+&apos;&apos;&apos;
+&apos;&apos;&apos; The menu is described from top to bottom. Each menu item receives a numeric and a string identifier.
+&apos;&apos;&apos;
+&apos;&apos;&apos; Menu items are either:
+&apos;&apos;&apos; - usual items
+&apos;&apos;&apos; - checkboxes
+&apos;&apos;&apos; - radio buttons
+&apos;&apos;&apos; - a menu separator
+&apos;&apos;&apos; Menu items can be decorated with icons and tooltips.
+&apos;&apos;&apos;
+&apos;&apos;&apos; Definitions:
+&apos;&apos;&apos; SubmenuCharacter: the character or the character string that identifies how menus are cascading
+&apos;&apos;&apos; Default = &quot;&gt;&quot;
+&apos;&apos;&apos; Can be set when invoking the Menu service
+&apos;&apos;&apos; ShortcutCharacter: the underline access key character
+&apos;&apos;&apos; Default = &quot;~&quot;
+&apos;&apos;&apos;
+&apos;&apos;&apos; Menus and submenus
+&apos;&apos;&apos; To create a menu with submenus, use the character defined in the
+&apos;&apos;&apos; SubmenuCharacter property while creating the menu entry to define where it will be
+&apos;&apos;&apos; placed. For instance, consider the following menu/submenu hierarchy.
+&apos;&apos;&apos; Item A
+&apos;&apos;&apos; Item B &gt; Item B.1
+&apos;&apos;&apos; Item B.2
+&apos;&apos;&apos; ------ (line separator)
+&apos;&apos;&apos; Item C &gt; Item C.1 &gt; Item C.1.1
+&apos;&apos;&apos; Item C.1.2
+&apos;&apos;&apos; Item C &gt; Item C.2 &gt; Item C.2.1
+&apos;&apos;&apos; Item C.2.2
+&apos;&apos;&apos; Next code will create the menu/submenu hierarchy
+&apos;&apos;&apos; With myMenu
+&apos;&apos;&apos; .AddItem(&quot;Item A&quot;)
+&apos;&apos;&apos; .AddItem(&quot;Item B&gt;Item B.1&quot;)
+&apos;&apos;&apos; .AddItem(&quot;Item B&gt;Item B.2&quot;)
+&apos;&apos;&apos; .AddItem(&quot;---&quot;)
+&apos;&apos;&apos; .AddItem(&quot;Item C&gt;Item C.1&gt;Item C.1.1&quot;)
+&apos;&apos;&apos; .AddItem(&quot;Item C&gt;Item C.1&gt;Item C.1.2&quot;)
+&apos;&apos;&apos; .AddItem(&quot;Item C&gt;Item C.2&gt;Item C.2.1&quot;)
+&apos;&apos;&apos; .AddItem(&quot;Item C&gt;Item C.2&gt;Item C.2.2&quot;)
+&apos;&apos;&apos; End With
+&apos;&apos;&apos;
+&apos;&apos;&apos; Service invocation:
+&apos;&apos;&apos; Dim ui As Object, oDoc As Object, myMenu As Object
+&apos;&apos;&apos; Set ui = CreateScriptService(&quot;UI&quot;)
+&apos;&apos;&apos; Set oDoc = ui.GetDocument(ThisComponent)
+&apos;&apos;&apos; Set myMenu = oDoc.CreateMenu(&quot;My own menu&quot;)
+&apos;&apos;&apos;
+&apos;&apos;&apos; Detailed user documentation:
+&apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/SF_Menu.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
+
+REM ============================================================= PRIVATE MEMBERS
+
+Private [Me] As Object
+Private ObjectType As String &apos; Must be MENU
+Private ServiceName As String
+
+
+&apos; Menu descriptors
+Private Component As Object &apos; the com.sun.star.lang.XComponent hosting the menu in its menubar
+Private MenuBar As Object &apos; com.sun.star.awt.XMenuBar or stardiv.Toolkit.VCLXMenuBar
+Private SubmenuChar As String &apos; Delimiter in menu trees
+Private MenuHeader As String &apos; Header of the menu
+Private MenuId As Integer &apos; Menu numeric identifier in the menubar
+Private MenuPosition As Integer &apos; Position of the menu on the menubar &gt;= 1
+Private PopupMenu As Object &apos; The underlying popup menu as a SF_PopupMenu object
+
+REM ============================================================ MODULE CONSTANTS
+
+Private Const _UnderlineAccessKeyChar = &quot;~&quot;
+Private Const _DefaultSubmenuChar = &quot;&gt;&quot;
+Private Const cstUnoPrefix = &quot;.uno:&quot;
+Private Const cstScriptArg = &quot;:::&quot;
+Private Const cstNormal = &quot;N&quot;
+Private Const cstCheck = &quot;C&quot;
+Private Const cstRadio = &quot;R&quot;
+
+REM ====================================================== CONSTRUCTOR/DESTRUCTOR
+
+REM -----------------------------------------------------------------------------
+Private Sub Class_Initialize()
+ Set [Me] = Nothing
+ ObjectType = &quot;MENU&quot;
+ ServiceName = &quot;SFWidgets.Menu&quot;
+ Set Component = Nothing
+ Set MenuBar = Nothing
+ SubmenuChar = _DefaultSubmenuChar
+ MenuHeader = &quot;&quot;
+ MenuId = -1
+ MenuPosition = 0
+ Set PopupMenu = Nothing
+End Sub &apos; SFWidgets.SF_Menu Constructor
+
+REM -----------------------------------------------------------------------------
+Private Sub Class_Terminate()
+ Call Class_Initialize()
+End Sub &apos; SFWidgets.SF_Menu Destructor
+
+REM -----------------------------------------------------------------------------
+Public Function Dispose() As Variant
+ PopupMenu.Dispose()
+ Call Class_Terminate()
+ Set Dispose = Nothing
+End Function &apos; SFWidgets.SF_Menu Explicit Destructor
+
+REM ================================================================== PROPERTIES
+
+REM -----------------------------------------------------------------------------
+Property Get ShortcutCharacter() As Variant
+&apos;&apos;&apos; The ShortcutCharacter property specifies character preceding the underline access key
+ ShortcutCharacter = _PropertyGet(&quot;ShortcutCharacter&quot;)
+End Property &apos; SFWidgets.SF_Menu.ShortcutCharacter (get)
+
+REM -----------------------------------------------------------------------------
+Property Get SubmenuCharacter() As Variant
+&apos;&apos;&apos; The SubmenuCharacter property specifies the character string indicating
+&apos;&apos;&apos; a sub-menu in a popup menu item
+ SubmenuCharacter = _PropertyGet(&quot;SubmenuCharacter&quot;)
+End Property &apos; SFWidgets.SF_Menu.SubmenuCharacter (get)
+
+REM ===================================================================== METHODS
+
+REM -----------------------------------------------------------------------------
+Public Function AddCheckBox(Optional ByVal MenuItem As Variant _
+ , Optional ByVal Name As Variant _
+ , Optional ByVal Status As Variant _
+ , Optional ByVal Icon As Variant _
+ , Optional ByVal Tooltip As Variant _
+ , Optional ByVal Command As Variant _
+ , Optional ByVal Script As Variant _
+ ) As Integer
+&apos;&apos;&apos; Insert in the popup menu a new entry as a checkbox
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; MenuItem: The text to be displayed in the menu entry.
+&apos;&apos;&apos; It determines also the hierarchy of the popup menu
+&apos;&apos;&apos; It is made up of all the components (separated by the &quot;SubmenuCharacter&quot;) of the menu branch
+&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;
+&apos;&apos;&apos; If the last component is equal to the &quot;SeparatorCharacter&quot;, a line separator is inserted
+&apos;&apos;&apos; Name: The name identifying the item. Default = the last component of MenuItem.
+&apos;&apos;&apos; Status: when True the item is selected. Default = False
+&apos;&apos;&apos; Icon: The path name of the icon to be displayed, without leading path separator
+&apos;&apos;&apos; The icons are stored in one of the &lt;install folder&gt;/share/config/images_*.zip files
+&apos;&apos;&apos; The exact file depends on the user options about the current icon set
+&apos;&apos;&apos; Use the (normal) slash &quot;/&quot; as path separator
+&apos;&apos;&apos; Example: &quot;cmd/sc_cut.png&quot;
+&apos;&apos;&apos; Tooltip: The help text to be displayed as a tooltip
+&apos;&apos;&apos; Command: A menu command like &quot;.uno:About&quot;. The validity of the command is not checked.
+&apos;&apos;&apos; Script: a Basic or Python script (determined by its URI notation) to be run when the item is clicked
+&apos;&apos;&apos; Read https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification
+&apos;&apos;&apos; Next string argument will be passed to the called script : a comma-separated string of 4 components:
+&apos;&apos;&apos; - the menu header
+&apos;&apos;&apos; - the name of the clicked menu item
+&apos;&apos;&apos; - the numeric identifier of the clicked menu item
+&apos;&apos;&apos; - &quot;1&quot; when the status is &quot;checked&quot;, otherwise &quot;0&quot;
+&apos;&apos;&apos; Arguments Command and Script are mutually exclusive.
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The numeric identification of the newly inserted item
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; Dim iId As Integer
+&apos;&apos;&apos; iId = myMenu.AddCheckBox(&quot;Menu top&gt;Checkbox item&quot;, Status := True, Command := &quot;Bold&quot;)
+
+Dim iId As Integer &apos; Return value
+Dim sCommand As String &apos; Alias of either Command or Script
+
+
+Const cstThisSub = &quot;SFWidgets.Menu.AddCheckBox&quot;
+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;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ iId = 0
+
+Check:
+ If IsMissing(Name) Or IsEmpty(Name) Then Name = &quot;&quot;
+ If IsMissing(Status) Or IsEmpty(Status) Then Status = False
+ If IsMissing(Icon) Or IsEmpty(Icon) Then Icon = &quot;&quot;
+ If IsMissing(Tooltip) Or IsEmpty(Tooltip) Then Tooltip = &quot;&quot;
+ If IsMissing(Command) Or IsEmpty(Command) Then Command = &quot;&quot;
+ If IsMissing(Script) Or IsEmpty(Script) Then Script = &quot;&quot;
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(MenuItem, &quot;MenuItem&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Name, &quot;Name&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Status, &quot;Status&quot;, ScriptForge.V_BOOLEAN) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Icon, &quot;Icon&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Tooltip, &quot;Tooltip&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Command, &quot;Command&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Script, &quot;Script&quot;, V_STRING) Then GoTo Catch
+ End If
+
+ If Len(Command) &gt; 0 Then
+ If Left(Command, Len(cstUnoPrefix)) = cstUnoPrefix Then sCommand = Command Else sCommand = cstUnoPrefix &amp; Command
+ Else
+ sCommand = Script &amp; cstScriptArg &amp; MenuHeader
+ End If
+
+Try:
+ iId = PopupMenu._AddItem(MenuItem, Name, cstCheck, Status, Icon, Tooltip, sCommand)
+
+Finally:
+ AddCheckBox = iId
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_Menu.AddCheckBox
+
+REM -----------------------------------------------------------------------------
+Public Function AddItem(Optional ByVal MenuItem As Variant _
+ , Optional ByVal Name As Variant _
+ , Optional ByVal Icon As Variant _
+ , Optional ByVal Tooltip As Variant _
+ , Optional ByVal Command As Variant _
+ , Optional ByVal Script As Variant _
+ ) As Integer
+&apos;&apos;&apos; Insert in the popup menu a new entry
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; MenuItem: The text to be displayed in the menu entry.
+&apos;&apos;&apos; It determines also the hierarchy of the popup menu
+&apos;&apos;&apos; It is made up of all the components (separated by the &quot;SubmenuCharacter&quot;) of the menu branch
+&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;
+&apos;&apos;&apos; If the last component is equal to &quot;---&quot;, a line separator is inserted and all other arguments are ignored
+&apos;&apos;&apos; Name: The name identifying the item. Default = the last component of MenuItem.
+&apos;&apos;&apos; Icon: The path name of the icon to be displayed, without leading path separator
+&apos;&apos;&apos; The icons are stored in one of the &lt;install folder&gt;/share/config/images_*.zip files
+&apos;&apos;&apos; The exact file depends on the user options about the current icon set
+&apos;&apos;&apos; Use the (normal) slash &quot;/&quot; as path separator
+&apos;&apos;&apos; Example: &quot;cmd/sc_cut.png&quot;
+&apos;&apos;&apos; Tooltip: The help text to be displayed as a tooltip
+&apos;&apos;&apos; Command: A menu command like &quot;.uno:About&quot;. The validity of the command is not checked.
+&apos;&apos;&apos; Script: a Basic or Python script (determined by its URI notation) to be run when the item is clicked
+&apos;&apos;&apos; Read https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification
+&apos;&apos;&apos; Next string argument will be passed to the called script : a comma-separated string of 4 components:
+&apos;&apos;&apos; - the menu header
+&apos;&apos;&apos; - the name of the clicked menu item
+&apos;&apos;&apos; - the numeric identifier of the clicked menu item
+&apos;&apos;&apos; - &quot;0&quot;
+&apos;&apos;&apos; Arguments Command and Script are mutually exclusive.
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The numeric identification of the newly inserted item
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; Dim iId1 As Integer, iId2 As Integer
+&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;)
+&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;)
+
+Dim iId As Integer &apos; Return value
+Dim sCommand As String &apos; Alias of either Command or Script
+
+Const cstThisSub = &quot;SFWidgets.Menu.AddItem&quot;
+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;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ iId = 0
+
+Check:
+ If IsMissing(Name) Or IsEmpty(Name) Then Name = &quot;&quot;
+ If IsMissing(Icon) Or IsEmpty(Icon) Then Icon = &quot;&quot;
+ If IsMissing(Tooltip) Or IsEmpty(Tooltip) Then Tooltip = &quot;&quot;
+ If IsMissing(Command) Or IsEmpty(Command) Then Command = &quot;&quot;
+ If IsMissing(Script) Or IsEmpty(Script) Then Script = &quot;&quot;
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(MenuItem, &quot;MenuItem&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Name, &quot;Name&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Icon, &quot;Icon&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Tooltip, &quot;Tooltip&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Command, &quot;Command&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Script, &quot;Script&quot;, V_STRING) Then GoTo Catch
+ End If
+
+ If Len(Command) &gt; 0 Then
+ If Left(Command, Len(cstUnoPrefix)) = cstUnoPrefix Then sCommand = Command Else sCommand = cstUnoPrefix &amp; Command
+ Else
+ sCommand = Script &amp; cstScriptArg &amp; MenuHeader
+ End If
+
+Try:
+ iId = PopupMenu._AddItem(MenuItem, Name, cstNormal, False, Icon, Tooltip, sCommand)
+
+Finally:
+ AddItem = iId
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_Menu.AddItem
+
+REM -----------------------------------------------------------------------------
+Public Function AddRadioButton(Optional ByVal MenuItem As Variant _
+ , Optional ByVal Name As Variant _
+ , Optional ByVal Status As Variant _
+ , Optional ByVal Icon As Variant _
+ , Optional ByVal Tooltip As Variant _
+ , Optional ByVal Command As Variant _
+ , Optional ByVal Script As Variant _
+ ) As Integer
+&apos;&apos;&apos; Insert in the popup menu a new entry as a radio button
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; MenuItem: The text to be displayed in the menu entry.
+&apos;&apos;&apos; It determines also the hieAddCheckBoxrarchy of the popup menu
+&apos;&apos;&apos; It is made up of all the components (separated by the &quot;SubmenuCharacter&quot;) of the menu branch
+&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;
+&apos;&apos;&apos; If the last component is equal to the &quot;SeparatorCharacter&quot;, a line separator is inserted
+&apos;&apos;&apos; Name: The name identifying the item. Default = the last component of MenuItem.
+&apos;&apos;&apos; Status: when True the item is selected. Default = False
+&apos;&apos;&apos; Icon: The path name of the icon to be displayed, without leading path separator
+&apos;&apos;&apos; The icons are stored in one of the &lt;install folder&gt;/share/config/images_*.zip files
+&apos;&apos;&apos; The exact file depends on the user options about the current icon set
+&apos;&apos;&apos; Use the (normal) slash &quot;/&quot; as path separator
+&apos;&apos;&apos; Example: &quot;cmd/sc_cut.png&quot;
+&apos;&apos;&apos; Tooltip: The help text to be displayed as a tooltip
+&apos;&apos;&apos; Command: A menu command like &quot;.uno:About&quot;. The validity of the command is not checked.
+&apos;&apos;&apos; Script: a Basic or Python script (determined by its URI notation) to be run when the item is clicked
+&apos;&apos;&apos; Read https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification
+&apos;&apos;&apos; Next string argument will be passed to the called script : a comma-separated string of 4 components:
+&apos;&apos;&apos; - the menu header
+&apos;&apos;&apos; - the name of the clicked menu item
+&apos;&apos;&apos; - the numeric identifier of theclicked menu item
+&apos;&apos;&apos; - &quot;1&quot; when the status is &quot;checked&quot;, otherwise &quot;0&quot;
+&apos;&apos;&apos; Arguments Command and Script are mutually exclusive.
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The numeric identification of the newly inserted item
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; Dim iId As Integer
+&apos;&apos;&apos; iId = myMenu.AddRadioButton(&quot;Menu top&gt;Radio item&quot;, Status := True, Command := &quot;Bold&quot;)
+
+Dim iId As Integer &apos; Return value
+Dim sCommand As String &apos; Alias of either Command or Script
+
+Const cstThisSub = &quot;SFWidgets.Menu.AddRadioButton&quot;
+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;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ iId = 0
+
+Check:
+ If IsMissing(Name) Or IsEmpty(Name) Then Name = &quot;&quot;
+ If IsMissing(Status) Or IsEmpty(Status) Then Status = False
+ If IsMissing(Icon) Or IsEmpty(Icon) Then Icon = &quot;&quot;
+ If IsMissing(Tooltip) Or IsEmpty(Tooltip) Then Tooltip = &quot;&quot;
+ If IsMissing(Command) Or IsEmpty(Command) Then Command = &quot;&quot;
+ If IsMissing(Script) Or IsEmpty(Script) Then Script = &quot;&quot;
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(MenuItem, &quot;MenuItem&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Name, &quot;Name&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Status, &quot;Status&quot;, ScriptForge.V_BOOLEAN) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Icon, &quot;Icon&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Tooltip, &quot;Tooltip&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Command, &quot;Command&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Script, &quot;Script&quot;, V_STRING) Then GoTo Catch
+ End If
+
+ If Len(Command) &gt; 0 Then
+ If Left(Command, Len(cstUnoPrefix)) = cstUnoPrefix Then sCommand = Command Else sCommand = cstUnoPrefix &amp; Command
+ Else
+ sCommand = Script &amp; cstScriptArg &amp; MenuHeader
+ End If
+
+Try:
+ iId = PopupMenu._AddItem(MenuItem, Name, cstRadio, Status, Icon, Tooltip, sCommand)
+
+Finally:
+ AddRadioButton = iId
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_Menu.AddRadioButton
+
+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;SFWidgets.Menu.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; SFWidgets.SF_Menu.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;AddCheckBox&quot; _
+ , &quot;AddItem&quot; _
+ , &quot;AddRadioButton&quot; _
+ )
+
+End Function &apos; SFWidgets.SF_Menu.Methods
+
+REM -----------------------------------------------------------------------------
+Public Function Properties() As Variant
+&apos;&apos;&apos; Return the list or properties of the Timer a.AddItem(&quot;B&gt;B1&quot;)class as an array
+
+ Properties = Array( _
+ &quot;ShortcutCharacter&quot; _
+ , &quot;SubmenuCharacter&quot; _
+ )
+
+End Function &apos; SFWidgets.SF_Menu.Properties
+
+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;SFWidgets.Menu.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; SFWidgets.SF_Menu.SetProperty
+
+REM =========================================================== PRIVATE FUNCTIONS
+
+REM -----------------------------------------------------------------------------
+Public Sub _Initialize(ByRef poComponent As Object _
+ , psMenuHeader As String _
+ , psBefore As String _
+ , piBefore As Integer _
+ , psSubmenuChar As String _
+ )
+&apos;&apos;&apos; Complete the object creation process:
+&apos;&apos;&apos; - Initialize the internal properties
+&apos;&apos;&apos; - Initialize the menubar
+&apos;&apos;&apos; - Determine the position and the internal id of the new menu
+&apos;&apos;&apos; - Create the menu and its attached popup menu
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; poComponent: the parent component where the menubar is to be searched for
+&apos;&apos;&apos; psMenuHeader: the header of the new menu. May or not contain a tilde &quot;~&quot;
+&apos;&apos;&apos; psBefore, piBefore: the menu before which to create the new menu, as a string or as a number
+&apos;&apos;&apos; psSubmenuChar: the submenus separator
+
+Dim oLayout As Object &apos; com.sun.star.comp.framework.LayoutManager
+Dim sName As String &apos; Menu name
+Dim iMenuId As Integer &apos; Menu identifier
+Dim oWindow As Object &apos; ui.Window type
+Dim oUi As Object : Set oUi = ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.UI&quot;)
+Dim i As Integer
+Const cstTilde = &quot;~&quot;
+
+Check:
+ &apos; How does the window look on top of which a menu is requested ?
+ Set oWindow = oUi._IdentifyWindow(poComponent)
+ With oWindow
+ If Not IsNull(.Frame) Then Set oLayout = .Frame.LayoutManager Else GoTo Finally
+ End With
+
+Try:
+ &apos; Initialize the menubar
+ Set MenuBar = oLayout.getElement(&quot;private:resource/menubar/menubar&quot;).XMenuBar
+
+ &apos; Determine the new menu identifier and its position
+ &apos; Identifier = largest current identifier + 1
+ MenuHeader = psMenuHeader
+ With MenuBar
+ For i = 0 To .ItemCount - 1
+ iMenuId = .getItemId(i)
+ If iMenuId &gt;= MenuId Then MenuId = iMenuId + 1
+ If piBefore &gt; 0 And piBefore = i + 1 Then
+ MenuPosition = piBefore
+ Else
+ sName = .getItemText(iMenuId)
+ If sName = psBefore Or Replace(sName, cstTilde, &quot;&quot;) = psBefore Then MenuPosition = i + 1
+ End If
+ Next i
+ If MenuPosition = 0 Then MenuPosition = .ItemCount + 1
+ End With
+
+ &apos; Store the submenu character
+ If Len(psSubmenuChar) &gt; 0 Then SubmenuChar = psSubmenuChar
+
+ &apos; Create the menu and the attached top popup menu
+ MenuBar.insertItem(MenuId, MenuHeader, 0, MenuPosition - 1)
+ PopupMenu = SFWidgets.SF_Register._NewPopupMenu(Array(Nothing, 0, 0, SubmenuChar))
+ PopupMenu.MenubarMenu = True &apos; Special indicator for menus depending on menubar
+ MenuBar.setPopupMenu(MenuId, PopupMenu.MenuRoot)
+
+ &apos; Initialize the listener on the top branch
+ SFWidgets.SF_MenuListener.SetMenuListener(PopupMenu.MenuRoot)
+
+Finally:
+ Exit Sub
+End Sub &apos; SFWidgets.SF_Menu._Initialize
+
+REM -----------------------------------------------------------------------------
+Private Function _PropertyGet(Optional ByVal psProperty As String) As Variant
+&apos;&apos;&apos; Return the value of the named property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psProperty: the name of the property
+
+Dim vGet As Variant &apos; Return value
+Dim cstThisSub As String
+Const cstSubArgs = &quot;&quot;
+
+ cstThisSub = &quot;SFWidgets.Menu.get&quot; &amp; psProperty
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+ ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+ _PropertyGet = Null
+
+ Select Case UCase(psProperty)
+ Case UCase(&quot;ShortcutCharacter&quot;)
+ _PropertyGet = _UnderlineAccessKeyChar
+ Case UCase(&quot;SubmenuCharacter&quot;)
+ _PropertyGet = SubmenuChar
+ Case Else
+ _PropertyGet = Null
+ End Select
+
+Finally:
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_Menu._PropertyGet
+
+REM -----------------------------------------------------------------------------
+Private Function _Repr() As String
+&apos;&apos;&apos; Convert the SF_Menu instance to a readable string, typically for debugging purposes (DebugPrint ...)
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Return:
+&apos;&apos;&apos; &quot;[Menu]: Name, Type (dialogname)
+ _Repr = &quot;[Menu]: &quot; &amp; SF_String.Represent(PopupMenu.MenuTree.Keys()) &amp; &quot;, &quot; &amp; SF_String.Represent(PopupMenu.MenuIdentification.Items())
+
+End Function &apos; SFWidgets.SF_Menu._Repr
+
+REM ============================================ END OF SFWIDGETS.SF_MENU
+</script:module> \ No newline at end of file
diff --git a/wizards/source/sfwidgets/SF_MenuListener.xba b/wizards/source/sfwidgets/SF_MenuListener.xba
new file mode 100644
index 0000000000..cb7839de58
--- /dev/null
+++ b/wizards/source/sfwidgets/SF_MenuListener.xba
@@ -0,0 +1,131 @@
+<?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_MenuListener" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
+REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
+REM === The SFWidgets 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_MenuListener
+&apos;&apos;&apos; ===============
+&apos;&apos;&apos; The current module is dedicated to the management of menu events + listeners, triggered by user actions,
+&apos;&apos;&apos; which cannot be defined with the Basic IDE
+&apos;&apos;&apos;
+&apos;&apos;&apos; Concerned listeners:
+&apos;&apos;&apos; com.sun.star.awt.XMenuListener
+&apos;&apos;&apos; allowing a user to select a menu command in user menus preset in the menubar
+&apos;&apos;&apos;
+&apos;&apos;&apos; The described events/listeners are processed by UNO listeners
+&apos;&apos;&apos;
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+
+REM ============================================================= PRIVATE MEMBERS
+
+Dim MenuListener As Object &apos; com.sun.star.awt.XMenuListener
+
+REM =========================================================== PRIVATE CONSTANTS
+
+Private Const _MenuListenerPrefix = &quot;_SFMENU_&quot;
+Private Const _MenuListener = &quot;com.sun.star.awt.XMenuListener&quot;
+Private Const cstUnoPrefix = &quot;.uno:&quot;
+Private Const cstScriptArg = &quot;:::&quot;
+
+REM ================================================================== EXCEPTIONS
+
+REM ============================================================== PUBLIC METHODS
+
+REM -----------------------------------------------------------------------------
+Public Sub SetMenuListener(poSubmenu As Object)
+&apos;&apos;&apos; Arm a menu listener on a submenu
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; poSubmenu: the targeted submenu
+
+Try:
+ If IsNull(MenuListener) Then Set MenuListener = CreateUnoListener(_MenuListenerPrefix, _MenuListener)
+ poSubmenu.addMenuListener(MenuListener)
+
+Finally:
+ Exit Sub
+End Sub &apos; SFWidgets.SF_MenuListener.SetMenuListener
+
+REM ============================================================= PRIVATE METHODS
+
+REM -----------------------------------------------------------------------------
+Sub _SFMENU_itemSelected(Optional poEvent As Object) &apos; com.sun.star.awt.MenuEvent
+&apos;&apos;&apos; Execute the command or the script associated with the actually selected item
+&apos;&apos;&apos; When a script, next argument is provided:
+&apos;&apos;&apos; a comma-separated string with 4 components
+&apos;&apos;&apos; - the menu header
+&apos;&apos;&apos; - the name of the selected menu entry (without tilde &quot;~&quot;)
+&apos;&apos;&apos; - the numeric identifier of the selected menu entry
+&apos;&apos;&apos; - the new status of the selected menu entry (&quot;0&quot; or &quot;1&quot;). Always &quot;0&quot; for usual items.
+
+Dim iMenuId As Integer
+Dim oMenu As Object &apos; stardiv.Toolkit.VCLXPopupMenu
+Dim sCommand As String &apos; Command associated with menu entry
+Dim bType As Boolean &apos; True when status is meaningful: item is radio button or checkbox
+Dim bStatus As Boolean &apos; Status of the menu item, always False for normal items
+Dim oFrame As Object &apos; com.sun.star.comp.framework.Frame
+Dim oDispatcher As Object &apos; com.sun.star.frame.DispatchHelper
+Dim vScript As Variant &apos; Split command in script/argument
+Dim oSession As Object : Set oSession = ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.Session&quot;)
+Dim oArgs() As new com.sun.star.beans.PropertyValue
+
+ On Local Error GoTo Catch &apos; Avoid stopping event scripts
+
+Try:
+ iMenuId = poEvent.MenuId
+ oMenu = poEvent.Source
+
+ With oMenu
+ &apos; Collect command (script or menu command) and status radiobuttons and checkboxes
+ sCommand = .getCommand(iMenuId)
+ bStatus = .isItemChecked(iMenuId)
+ End With
+
+ If Len(sCommand) &gt; 0 Then
+ &apos; A menu has been clicked necessarily in the current window (Document) or one of its subcomponents (FormDocument)
+ Set oFrame = StarDesktop.ActiveFrame
+ If oFrame.Frames.Count &gt; 0 Then Set oFrame = oFrame.getActiveFrame()
+ &apos; Command or script ?
+ If Left(sCommand, Len(cstUnoPrefix)) = cstUnoPrefix Then
+ &apos; Execute uno command
+ Set oDispatcher = ScriptForge.SF_Utils._GetUNOService(&quot;DispatchHelper&quot;)
+ oDispatcher.executeDispatch(oFrame, sCommand, &quot;&quot;, 0, oArgs())
+ oFrame.activate()
+ Else
+ &apos; Execute script
+ vScript = Split(sCommand, cstScriptArg)
+ oSession._ExecuteScript(vScript(0), vScript(1) &amp; &quot;,&quot; &amp; Iif(bStatus, &quot;1&quot;, &quot;0&quot;)) &apos; Return value is ignored
+ End If
+ End If
+
+Finally:
+ Exit Sub
+Catch:
+ GoTo Finally
+End Sub &apos; SFWidgets.SF_MenuListener._SFMENU_itemSelected
+
+REM -----------------------------------------------------------------------------
+Sub _SFMENU_itemHighlighted(Optional poEvent As Object) &apos; com.sun.star.awt.MenuEvent
+ Exit Sub
+End Sub &apos; SFWidgets.SF_MenuListener._SFMENU_itemHighlighted
+
+Sub _SFMENU_itemActivated(Optional poEvent As Object) &apos; com.sun.star.awt.MenuEvent
+ Exit Sub
+End Sub &apos; SFWidgets.SF_MenuListener._SFMENU_itemActivated
+
+Sub _SFMENU_itemDeactivated(Optional poEvent As Object) &apos; com.sun.star.awt.MenuEvent
+ Exit Sub
+End Sub &apos; SFWidgets.SF_MenuListener._SFMENU_itemDeactivated
+
+Sub _SFMENU_disposing(Optional poEvent As Object) &apos; com.sun.star.awt.MenuEvent
+ Exit Sub
+End Sub &apos; SFWidgets.SF_MenuListener._SFMENU_disposing
+
+REM ============================================ END OF SFWIDGETS.SF_MENULISTENER
+</script:module> \ No newline at end of file
diff --git a/wizards/source/sfwidgets/SF_PopupMenu.xba b/wizards/source/sfwidgets/SF_PopupMenu.xba
new file mode 100644
index 0000000000..3d5ba65a80
--- /dev/null
+++ b/wizards/source/sfwidgets/SF_PopupMenu.xba
@@ -0,0 +1,801 @@
+<?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_PopupMenu" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
+REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
+REM === The SFWidgets 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_PopupMenu
+&apos;&apos;&apos; ============
+&apos;&apos;&apos; Display a popup menu anywhere and any time
+&apos;&apos;&apos;
+&apos;&apos;&apos; A popup menu is usually triggered by a mouse action (typically a right-click) on a dialog, a form
+&apos;&apos;&apos; or one of their controls. In this case the menu will be displayed below the clicked area.
+&apos;&apos;&apos; When triggered by other events, including in the normal flow of a user script, the script should
+&apos;&apos;&apos; provide the coordinates of the topleft edge of the menu versus the actual component.
+&apos;&apos;&apos;
+&apos;&apos;&apos; The menu is described from top to bottom. Each menu item receives a numeric and a string identifier.
+&apos;&apos;&apos; The Execute() method returns the item selected by the user.
+&apos;&apos;&apos;
+&apos;&apos;&apos; Menu items are either:
+&apos;&apos;&apos; - usual items
+&apos;&apos;&apos; - checkboxes
+&apos;&apos;&apos; - radio buttons
+&apos;&apos;&apos; - a menu separator
+&apos;&apos;&apos; Menu items can be decorated with icons and tooltips.
+&apos;&apos;&apos;
+&apos;&apos;&apos; Definitions:
+&apos;&apos;&apos; SubmenuCharacter: the character or the character string that identifies how menus are cascading
+&apos;&apos;&apos; Default = &quot;&gt;&quot;
+&apos;&apos;&apos; Can be set when invoking the PopupMenu service
+&apos;&apos;&apos; ShortcutCharacter: the underline access key character
+&apos;&apos;&apos; Default = &quot;~&quot;
+&apos;&apos;&apos;
+&apos;&apos;&apos; Service invocation:
+&apos;&apos;&apos; Sub OpenMenu(Optional poMouseEvent As Object)
+&apos;&apos;&apos; Dim myMenu As Object
+&apos;&apos;&apos; Set myMenu = CreateScriptService(&quot;SFWidgets.PopupMenu&quot;, poMouseEvent, , , &quot;&gt;&gt;&quot;) &apos; Usual case
+&apos;&apos;&apos; &apos; or
+&apos;&apos;&apos; Set myMenu = CreateScriptService(&quot;SFWidgets.PopupMenu&quot;, , X, Y, &quot; | &quot;) &apos; Use X and Y coordinates to place the menu
+&apos;&apos;&apos;
+&apos;&apos;&apos; Menus and submenus
+&apos;&apos;&apos; To create a popup menu with submenus, use the character defined in the
+&apos;&apos;&apos; SubmenuCharacter property while creating the menu entry to define where it will be
+&apos;&apos;&apos; placed. For instance, consider the following menu/submenu hierarchy.
+&apos;&apos;&apos; Item A
+&apos;&apos;&apos; Item B &gt; Item B.1
+&apos;&apos;&apos; Item B.2
+&apos;&apos;&apos; ------ (line separator)
+&apos;&apos;&apos; Item C &gt; Item C.1 &gt; Item C.1.1
+&apos;&apos;&apos; Item C.1.2
+&apos;&apos;&apos; Item C &gt; Item C.2 &gt; Item C.2.1
+&apos;&apos;&apos; Item C.2.2
+&apos;&apos;&apos; Next code will create the menu/submenu hierarchy
+&apos;&apos;&apos; With myMenu
+&apos;&apos;&apos; .AddItem(&quot;Item A&quot;)
+&apos;&apos;&apos; .AddItem(&quot;Item B&gt;Item B.1&quot;)
+&apos;&apos;&apos; .AddItem(&quot;Item B&gt;Item B.2&quot;)
+&apos;&apos;&apos; .AddItem(&quot;---&quot;)
+&apos;&apos;&apos; .AddItem(&quot;Item C&gt;Item C.1&gt;Item C.1.1&quot;)
+&apos;&apos;&apos; .AddItem(&quot;Item C&gt;Item C.1&gt;Item C.1.2&quot;)
+&apos;&apos;&apos; .AddItem(&quot;Item C&gt;Item C.2&gt;Item C.2.1&quot;)
+&apos;&apos;&apos; .AddItem(&quot;Item C&gt;Item C.2&gt;Item C.2.2&quot;)
+&apos;&apos;&apos; End With
+&apos;&apos;&apos;
+&apos;&apos;&apos; Example 1: simulate a subset of the View menu in the menubar of the Basic IDE
+&apos;&apos;&apos; Sub OpenMenu(Optional poMouseEvent As Object)
+&apos;&apos;&apos; Dim myMenu As Object, vChoice As Variant
+&apos;&apos;&apos; Set myMenu = CreateScriptService(&quot;SFWidgets.PopupMenu&quot;, poMouseEvent)
+&apos;&apos;&apos; With myMenu
+&apos;&apos;&apos; .AddCheckBox(&quot;View&gt;Toolbars&gt;Dialog&quot;)
+&apos;&apos;&apos; .AddCheckBox(&quot;View&gt;Toolbars&gt;Find&quot;, Status := True)
+&apos;&apos;&apos; .AddCheckBox(&quot;View&gt;Status Bar&quot;, Status := True)
+&apos;&apos;&apos; .AddItem(&quot;View&gt;Full Screen&quot;, Name := &quot;FULLSCREEN&quot;)
+&apos;&apos;&apos; vChoice = .Execute(False) &apos; When 1st checkbox is clicked, return &quot;Dialog&quot;
+&apos;&apos;&apos; &apos; When last item is clicked, return &quot;FULLSCREEN&quot;
+&apos;&apos;&apos; .Dispose()
+&apos;&apos;&apos; End With
+&apos;&apos;&apos;
+&apos;&apos;&apos; Example 2: jump to another sheet of a Calc document
+&apos;&apos;&apos; &apos; Link next Sub to the &quot;Mouse button released&quot; event of a form control of a Calc sheet
+&apos;&apos;&apos; Sub JumpToSheet(Optional poEvent As Object)
+&apos;&apos;&apos; Dim myMenu As Object, sChoice As String, myDoc As Object, vSheets As Variant, sSheet As String
+&apos;&apos;&apos; Set myMenu = CreateScriptService(&quot;SFWidgets.PopupMenu&quot;, poEvent)
+&apos;&apos;&apos; Set myDoc = CreateScriptService(&quot;Calc&quot;, ThisComponent)
+&apos;&apos;&apos; vSheets = myDoc.Sheets
+&apos;&apos;&apos; For Each sSheet In vSheets
+&apos;&apos;&apos; myMenu.AddItem(sSheet)
+&apos;&apos;&apos; Next sSheet
+&apos;&apos;&apos; sChoice = myMenu.Execute(False) &apos; Return sheet name, not sheet index
+&apos;&apos;&apos; If sChoice &lt;&gt; &quot;&quot; Then myDoc.Activate(sChoice)
+&apos;&apos;&apos; myDoc.Dispose()
+&apos;&apos;&apos; myMenu.Dispose()
+&apos;&apos;&apos; End Sub
+&apos;&apos;&apos;
+&apos;&apos;&apos;
+&apos;&apos;&apos; Detailed user documentation:
+&apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_popupmenu.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
+
+REM ============================================================= PRIVATE MEMBERS
+
+Private [Me] As Object
+Private ObjectType As String &apos; Must be POPUPMENU
+Private ServiceName As String
+
+
+&apos; Menu descriptors
+Private MenuTree As Variant &apos; Dictionary treename - XPopupMenu pair
+Private MenuIdentification As Variant &apos; Dictionary item ID - item name
+Private SubmenuChar As String &apos; Delimiter in menu trees
+Private MenuRoot As Object &apos; stardiv.vcl.PopupMenu or com.sun.star.awt.XPopupMenu
+Private LastItem As Integer &apos; Every item has its entry number. This is the last one
+Private Rectangle As Object &apos; com.sun.star.awt.Rectangle
+Private PeerWindow As Object &apos; com.sun.star.awt.XWindowPeer
+Private MenubarMenu As Boolean &apos; When True, the actual popup menu depends on a menubar item
+
+REM ============================================================ MODULE CONSTANTS
+
+Private Const _UnderlineAccessKeyChar = &quot;~&quot;
+Private Const _DefaultSubmenuChar = &quot;&gt;&quot;
+Private Const _SeparatorChar = &quot;---&quot;
+Private Const _IconsDirectory = &quot;private:graphicrepository/&quot; &apos; Refers to &lt;install folder&gt;/share/config/images_*.zip.
+Private Const cstUnoPrefix = &quot;.uno:&quot;
+Private Const cstNormal = &quot;N&quot;
+Private Const cstCheck = &quot;C&quot;
+Private Const cstRadio = &quot;R&quot;
+
+REM ====================================================== CONSTRUCTOR/DESTRUCTOR
+
+REM -----------------------------------------------------------------------------
+Private Sub Class_Initialize()
+ Set [Me] = Nothing
+ ObjectType = &quot;POPUPMENU&quot;
+ ServiceName = &quot;SFWidgets.PopupMenu&quot;
+ Set MenuTree = Nothing
+ Set MenuIdentification = Nothing
+ SubmenuChar = _DefaultSubmenuChar
+ Set MenuRoot = Nothing
+ LastItem = 0
+ Set Rectangle = Nothing
+ Set PeerWindow = Nothing
+ MenubarMenu = False
+End Sub &apos; SFWidgets.SF_PopupMenu Constructor
+
+REM -----------------------------------------------------------------------------
+Private Sub Class_Terminate()
+ Call Class_Initialize()
+End Sub &apos; SFWidgets.SF_PopupMenu Destructor
+
+REM -----------------------------------------------------------------------------
+Public Function Dispose() As Variant
+ If Not IsNull(MenuTree) Then Set MenuTree = MenuTree.Dispose()
+ If Not IsNull(MenuIdentification) Then Set MenuIdentification = MenuIdentification.Dispose()
+ Call Class_Terminate()
+ Set Dispose = Nothing
+End Function &apos; SFWidgets.SF_PopupMenu Explicit Destructor
+
+REM ================================================================== PROPERTIES
+
+REM -----------------------------------------------------------------------------
+Property Get ShortcutCharacter() As Variant
+&apos;&apos;&apos; The ShortcutCharacter property specifies character preceding the underline access key
+ ShortcutCharacter = _PropertyGet(&quot;ShortcutCharacter&quot;)
+End Property &apos; SFWidgets.SF_PopupMenu.ShortcutCharacter (get)
+
+REM -----------------------------------------------------------------------------
+Property Get SubmenuCharacter() As Variant
+&apos;&apos;&apos; The SubmenuCharacter property specifies the character string indicating
+&apos;&apos;&apos; a sub-menu in a popup menu item
+ SubmenuCharacter = _PropertyGet(&quot;SubmenuCharacter&quot;)
+End Property &apos; SFWidgets.SF_PopupMenu.SubmenuCharacter (get)
+
+REM ===================================================================== METHODS
+
+REM -----------------------------------------------------------------------------
+Public Function AddCheckBox(Optional ByVal MenuItem As Variant _
+ , Optional ByVal Name As Variant _
+ , Optional ByVal Status As Variant _
+ , Optional ByVal Icon As Variant _
+ , Optional ByVal Tooltip As Variant _
+ ) As Integer
+&apos;&apos;&apos; Insert in the popup menu a new entry
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; MenuItem: The text to be displayed in the menu entry.
+&apos;&apos;&apos; It determines also the hierarchy of the popup menu
+&apos;&apos;&apos; It is made up of all the components (separated by the &quot;SubmenuCharacter&quot;) of the menu branch
+&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;
+&apos;&apos;&apos; If the last component is equal to the &quot;SeparatorCharacter&quot;, a line separator is inserted
+&apos;&apos;&apos; Name: The name to be returned by the Execute() method if this item is clicked
+&apos;&apos;&apos; Default = the last component of MenuItem
+&apos;&apos;&apos; Status: when True the item is selected. Default = False
+&apos;&apos;&apos; Icon: The path name of the icon to be displayed, without leading path separator
+&apos;&apos;&apos; The icons are stored in one of the &lt;install folder&gt;/share/config/images_*.zip files
+&apos;&apos;&apos; The exact file depends on the user options about the current icon set
+&apos;&apos;&apos; Use the (normal) slash &quot;/&quot; as path separator
+&apos;&apos;&apos; Example: &quot;cmd/sc_cut.png&quot;
+&apos;&apos;&apos; Tooltip: The help text to be displayed as a tooltip
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The numeric identification of the newly inserted item
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; Dim myMenu As Object, iId As Integer
+&apos;&apos;&apos; Set myMenu = CreateScriptService(&quot;SFWidgets.PopupMenu&quot;, poEvent)
+&apos;&apos;&apos; iId = myMenu.AddCheckBox(&quot;Menu top&gt;Checkbox item&quot;, Status := True)
+
+Dim iId As Integer &apos; Return value
+
+Const cstThisSub = &quot;SFWidgets.PopupMenu.AddCheckBox&quot;
+Const cstSubArgs = &quot;MenuItem, [Name=&quot;&quot;&quot;&quot;], [Status=False], [Icon=&quot;&quot;&quot;&quot;], [Tooltip=&quot;&quot;&quot;&quot;]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ iId = 0
+
+Check:
+ If IsMissing(Name) Or IsEmpty(Name) Then Name = &quot;&quot;
+ If IsMissing(Status) Or IsEmpty(Status) Then Status = False
+ If IsMissing(Icon) Or IsEmpty(Icon) Then Icon = &quot;&quot;
+ If IsMissing(Tooltip) Or IsEmpty(Tooltip) Then Tooltip = &quot;&quot;
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(MenuItem, &quot;MenuItem&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Name, &quot;Name&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Status, &quot;Status&quot;, ScriptForge.V_BOOLEAN) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Icon, &quot;Icon&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Tooltip, &quot;Tooltip&quot;, V_STRING) Then GoTo Catch
+ End If
+
+Try:
+ iId = _AddItem(MenuItem, Name, cstCheck, Status, Icon, Tooltip)
+
+Finally:
+ AddCheckBox = iId
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_PopupMenu.AddCheckBox
+
+REM -----------------------------------------------------------------------------
+Public Function AddItem(Optional ByVal MenuItem As Variant _
+ , Optional ByVal Name As Variant _
+ , Optional ByVal Icon As Variant _
+ , Optional ByVal Tooltip As Variant _
+ ) As Integer
+&apos;&apos;&apos; Insert in the popup menu a new entry
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; MenuItem: The text to be displayed in the menu entry.
+&apos;&apos;&apos; It determines also the hierarchy of the popup menu
+&apos;&apos;&apos; It is made up of all the components (separated by the &quot;SubmenuCharacter&quot;) of the menu branch
+&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;
+&apos;&apos;&apos; If the last component is equal to &quot;---&quot;, a line separator is inserted and all other arguments are ignored
+&apos;&apos;&apos; Name: The name to be returned by the Execute() method if this item is clicked
+&apos;&apos;&apos; Default = the last component of MenuItem
+&apos;&apos;&apos; Icon: The path name of the icon to be displayed, without leading path separator
+&apos;&apos;&apos; The icons are stored in one of the &lt;install folder&gt;/share/config/images_*.zip files
+&apos;&apos;&apos; The exact file depends on the user options about the current icon set
+&apos;&apos;&apos; Use the (normal) slash &quot;/&quot; as path separator
+&apos;&apos;&apos; Example: &quot;cmd/sc_cut.png&quot;
+&apos;&apos;&apos; Tooltip: The help text to be displayed as a tooltip
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The numeric identification of the newly inserted item
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; Dim myMenu As Object, iId As Integer
+&apos;&apos;&apos; Set myMenu = CreateScriptService(&quot;SFWidgets.PopupMenu&quot;, poEvent)
+&apos;&apos;&apos; iId = myMenu.AddItem(&quot;Menu top&gt;Normal item&quot;, Icon := &quot;cmd.sc_cut.png&quot;)
+
+Dim iId As Integer &apos; Return value
+
+Const cstThisSub = &quot;SFWidgets.PopupMenu.AddItem&quot;
+Const cstSubArgs = &quot;MenuItem, [Name=&quot;&quot;&quot;&quot;], [Icon=&quot;&quot;&quot;&quot;], [Tooltip=&quot;&quot;&quot;&quot;]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ iId = 0
+
+Check:
+ If IsMissing(Name) Or IsEmpty(Name) Then Name = &quot;&quot;
+ If IsMissing(Icon) Or IsEmpty(Icon) Then Icon = &quot;&quot;
+ If IsMissing(Tooltip) Or IsEmpty(Tooltip) Then Tooltip = &quot;&quot;
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(MenuItem, &quot;MenuItem&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Name, &quot;Name&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Icon, &quot;Icon&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Tooltip, &quot;Tooltip&quot;, V_STRING) Then GoTo Catch
+ End If
+
+Try:
+ iId = _AddItem(MenuItem, Name, cstNormal, False, Icon, Tooltip)
+
+Finally:
+ AddItem = iId
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_PopupMenu.AddItem
+
+REM -----------------------------------------------------------------------------
+Public Function AddRadioButton(Optional ByVal MenuItem As Variant _
+ , Optional ByVal Name As Variant _
+ , Optional ByVal Status As Variant _
+ , Optional ByVal Icon As Variant _
+ , Optional ByVal Tooltip As Variant _
+ ) As Integer
+&apos;&apos;&apos; Insert in the popup menu a new entry as a radio button
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; MenuItem: The text to be displayed in the menu entry.
+&apos;&apos;&apos; It determines also the hieAddCheckBoxrarchy of the popup menu
+&apos;&apos;&apos; It is made up of all the components (separated by the &quot;SubmenuCharacter&quot;) of the menu branch
+&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;
+&apos;&apos;&apos; If the last component is equal to the &quot;SeparatorCharacter&quot;, a line separator is inserted
+&apos;&apos;&apos; Name: The name to be returned by the Execute() method if this item is clicked
+&apos;&apos;&apos; Default = the last component of MenuItem
+&apos;&apos;&apos; Status: when True the item is selected. Default = False
+&apos;&apos;&apos; Icon: The path name of the icon to be displayed, without leading path separator
+&apos;&apos;&apos; The icons are stored in one of the &lt;install folder&gt;/share/config/images_*.zip files
+&apos;&apos;&apos; The exact file depends on the user options about the current icon set
+&apos;&apos;&apos; Use the (normal) slash &quot;/&quot; as path separator
+&apos;&apos;&apos; Example: &quot;cmd/sc_cut.png&quot;
+&apos;&apos;&apos; Tooltip: The help text to be displayed as a tooltip
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The numeric identification of the newly inserted item
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; Dim myMenu As Object, iId As Integer
+&apos;&apos;&apos; Set myMenu = CreateScriptService(&quot;SFWidgets.PopupMenu&quot;, poEvent)
+&apos;&apos;&apos; iId = myMenu.AddRadioButton(&quot;Menu top&gt;Radio item&quot;, Status := True)
+
+Dim iId As Integer &apos; Return value
+
+Const cstThisSub = &quot;SFWidgets.PopupMenu.AddRadioButton&quot;
+Const cstSubArgs = &quot;MenuItem, [Name=&quot;&quot;&quot;&quot;], [Status=False], [Icon=&quot;&quot;&quot;&quot;], [Tooltip=&quot;&quot;&quot;&quot;]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ iId = 0
+
+Check:
+ If IsMissing(Name) Or IsEmpty(Name) Then Name = &quot;&quot;
+ If IsMissing(Status) Or IsEmpty(Status) Then Status = False
+ If IsMissing(Icon) Or IsEmpty(Icon) Then Icon = &quot;&quot;
+ If IsMissing(Tooltip) Or IsEmpty(Tooltip) Then Tooltip = &quot;&quot;
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(MenuItem, &quot;MenuItem&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Name, &quot;Name&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Status, &quot;Status&quot;, ScriptForge.V_BOOLEAN) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Icon, &quot;Icon&quot;, V_STRING) Then GoTo Catch
+ If Not ScriptForge.SF_Utils._Validate(Tooltip, &quot;Tooltip&quot;, V_STRING) Then GoTo Catch
+ End If
+
+Try:
+ iId = _AddItem(MenuItem, Name, cstRadio, Status, Icon, Tooltip)
+
+Finally:
+ AddRadioButton = iId
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_PopupMenu.AddRadioButton
+
+REM -----------------------------------------------------------------------------
+Public Function Execute(Optional ByVal ReturnId As Variant) As Variant
+&apos;&apos;&apos; Display the popup menu and return the menu item clicked by the user
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; ReturnId: When True (default), return the unique ID of the clicked item, otherwise return its name
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The numeric identification of clicked item or its name
+&apos;&apos;&apos; The returned value is 0 or &quot;&quot; (depending on ReturnId) when the menu is cancelled
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; Sub OpenMenu(Optional poMouseEvent As Object)
+&apos;&apos;&apos; Dim myMenu As Object, vChoice As Variant
+&apos;&apos;&apos; Set myMenu = CreateScriptService(&quot;SFWidgets.PopupMenu&quot;, poMouseEvent)
+&apos;&apos;&apos; With myMenu
+&apos;&apos;&apos; .AddCheckBox(&quot;View&gt;Toolbars&gt;Dialog&quot;)
+&apos;&apos;&apos; .AddCheckBox(&quot;View&gt;Toolbars&gt;Find&quot;, STatus := True)
+&apos;&apos;&apos; .AddCheckBox(&quot;View&gt;Status Bar&quot;, STatus := True)
+&apos;&apos;&apos; .AddItem(&quot;View&gt;Full Screen&quot;, Name := &quot;FULLSCREEN&quot;)
+&apos;&apos;&apos; vChoice = .Execute(False) &apos; When 1st checkbox is clicked, return &quot;Dialog&quot;
+&apos;&apos;&apos; &apos; When last item is clicked, return &quot;FULLSCREEN&quot;
+&apos;&apos;&apos; End With
+
+Dim vMenuItem As Variant &apos; Return value
+
+Const cstThisSub = &quot;SFWidgets.PopupMenu.Execute&quot;
+Const cstSubArgs = &quot;[ReturnId=True]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ vMenuItem = 0
+
+Check:
+ If IsMissing(ReturnId) Or IsEmpty(ReturnId) Then ReturnId = True
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not ScriptForge.SF_Utils._Validate(ReturnId, &quot;ReturnId&quot;, ScriptForge.V_BOOLEAN) Then GoTo Catch
+ End If
+ If Not ReturnId Then vMenuItem = &quot;&quot;
+
+Try:
+ vMenuItem = MenuRoot.Execute(PeerWindow, Rectangle, com.sun.star.awt.PopupMenuDirection.EXECUTE_DEFAULT)
+ If Not ReturnId Then vMenuItem = MenuIdentification.Item(CStr(vMenuItem))
+
+Finally:
+ Execute = vMenuItem
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_PopupMenu.Execute
+
+REM -----------------------------------------------------------------------------
+Public Function GetProperty(Optional ByVal PropertyName As Variant) As Variant
+&apos;&apos;&apos; Return the actual value of the given property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; PropertyName: the name of the property as a string
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The actual value of the property
+&apos;&apos;&apos; 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;SFWidgets.PopupMenu.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; SFWidgets.SF_PopupMenu.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;AddCheckBox&quot; _
+ , &quot;AddItem&quot; _
+ , &quot;AddRadioButton&quot; _
+ , &quot;Execute&quot; _
+ )
+
+End Function &apos; SFWidgets.SF_PopupMenu.Methods
+
+REM -----------------------------------------------------------------------------
+Public Function Properties() As Variant
+&apos;&apos;&apos; Return the list or properties of the Timer a.AddItem(&quot;B&gt;B1&quot;)class as an array
+
+ Properties = Array( _
+ &quot;ShortcutCharacter&quot; _
+ , &quot;SubmenuCharacter&quot; _
+ )
+
+End Function &apos; SFWidgets.SF_PopupMenu.Properties
+
+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;SFWidgets.PopupMenu.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; SFWidgets.SF_PopupMenu.SetProperty
+
+REM =========================================================== PRIVATE FUNCTIONS
+
+REM -----------------------------------------------------------------------------
+Public Function _AddItem(ByVal MenuItem As String _
+ , ByVal Name As String _
+ , ByVal ItemType As String _
+ , ByVal Status As Boolean _
+ , ByVal Icon As String _
+ , ByVal Tooltip As String _
+ , Optional ByVal Command As String _
+ ) As Integer
+&apos;&apos;&apos; Insert in the popup menu a new entry
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; MenuItem: The text to be displayed in the menu entry.
+&apos;&apos;&apos; It determines also the hierarchy of the popup menu
+&apos;&apos;&apos; It is made up of all the components (separated by the &quot;SubmenuCharacter&quot;) of the menu branch
+&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;
+&apos;&apos;&apos; If the last component is equal to the &quot;SeparatorCharacter&quot;, a line separator is inserted
+&apos;&apos;&apos; Name: The name to be returned by the Execute() method if this item is clicked
+&apos;&apos;&apos; Default = the last component of MenuItem
+&apos;&apos;&apos; ItemType: &quot;N&quot;(ormal, &quot;C&quot;(heck) or &quot;R&quot;(adio)
+&apos;&apos;&apos; Status: when True the item is selected
+&apos;&apos;&apos; Icon: The path name of the icon to be displayed, without leading path separator
+&apos;&apos;&apos; The icons are stored in one of the &lt;install folder&gt;/share/config/images_*.zip files
+&apos;&apos;&apos; The exact file depends on the user options about the current icon set
+&apos;&apos;&apos; Use the (normal) slash &quot;/&quot; as path separator
+&apos;&apos;&apos; Example: &quot;cmd/sc_cut.png&quot;
+&apos;&apos;&apos; Tooltip: The help text to be displayed as a tooltip
+&apos;&apos;&apos; Command: only for menubar menus
+&apos;&apos;&apos; Either a uo command like &quot;.uno:About&quot;
+&apos;&apos;&apos; or a script to be run: script URI ::: string argument to be passed to the script
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The numeric identification of the newly inserted item
+
+Dim iId As Integer &apos; Return value
+Dim vSplit As Variant &apos; Split menu item
+Dim sMenu As String &apos; Submenu where to attach the new item, as a string
+Dim oMenu As Object &apos; Submenu where to attach the new item, as an object
+Dim sName As String &apos; The text displayed in the menu box
+Dim oImage As Object &apos; com.sun.star.graphic.XGraphic
+Dim sCommand As String &apos; Alias of Command completed with arguments
+Const cstCommandSep = &quot;,&quot;
+
+ On Local Error GoTo Catch
+ iId = 0
+ If IsMissing(Command) Then Command = &quot;&quot;
+
+Try:
+ &apos; Run through the upper menu tree
+ vSplit = _SplitMenuItem(MenuItem)
+
+ &apos; Create and determine the menu to which to attach the new item
+ sMenu = vSplit(0)
+ Set oMenu = _GetPopupMenu(sMenu) &apos; Run through the upper menu tree and retain the last branch
+
+ &apos; Insert the new item
+ LastItem = LastItem + 1
+ sName = vSplit(1)
+
+ With oMenu
+ If sName = _SeparatorChar Then
+ .insertSeparator(-1)
+ Else
+ Select Case ItemType
+ Case cstNormal
+ .insertItem(LastItem, sName, 0, -1)
+ Case cstCheck
+ .insertItem(LastItem, sName, com.sun.star.awt.MenuItemStyle.CHECKABLE + com.sun.star.awt.MenuItemStyle.AUTOCHECK, -1)
+ .checkItem(LastItem, Status)
+ Case cstRadio
+ .insertItem(LastItem, sName, com.sun.star.awt.MenuItemStyle.RADIOCHECK + com.sun.star.awt.MenuItemStyle.AUTOCHECK, -1)
+ .checkItem(LastItem, Status)
+ End Select
+
+ &apos; Store the ID - Name relation
+ If Len(Name) = 0 Then Name = Replace(sName, _UnderlineAccessKeyChar, &quot;&quot;)
+ MenuIdentification.Add(CStr(LastItem), Name)
+
+ &apos; Add the icon when relevant
+ If Len(Icon) &gt; 0 Then
+ Set oImage = _GetImageFromUrl(_IconsDirectory &amp; Icon)
+ If Not IsNull(oImage) Then .setItemImage(LastItem, oImage, False)
+ End If
+
+ &apos; Add the tooltip when relevant
+ If Len(Tooltip) &gt; 0 Then .setTipHelpText(LastItem, Tooltip)
+
+ &apos; Add the command: UNO command or script to run - menubar menus only
+ If Len(Command) &gt; 0 Then
+ If Left(Command, Len(cstUnoPrefix)) = cstUnoPrefix Then
+ sCommand = Command
+ Else
+ sCommand = Command &amp; cstCommandSep &amp; Name &amp; cstCommandSep &amp; CStr(LastItem)
+ End If
+ .setCommand(LastItem, sCommand)
+ End If
+ End If
+ End With
+
+ iId = LastItem
+
+Finally:
+ _AddItem = iId
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_PopupMenu._AddItem
+
+REM -----------------------------------------------------------------------------
+Private Function _GetImageFromURL(ByVal psUrl as String) As Object
+&apos;&apos;&apos; Returns a com.sun.star.graphic.XGraphic instance based on the given URL
+&apos;&apos;&apos; The returned object is intended to be inserted as an icon in the popup menu
+&apos;&apos;&apos; Derived from &quot;Useful Macro Information For OpenOffice&quot; By Andrew Pitonyak
+
+Dim vMediaProperties As Variant &apos; Array of com.sun.star.beans.PropertyValue
+Dim oGraphicProvider As Object &apos; com.sun.star.graphic.GraphicProvider
+Dim oImage As Object &apos; Return value
+
+ On Local Error GoTo Catch &apos; Ignore errors
+ Set oImage = Nothing
+
+Try:
+ &apos; Create graphic provider instance to load images from files.
+ Set oGraphicProvider = CreateUnoService(&quot;com.sun.star.graphic.GraphicProvider&quot;)
+
+ &apos; Set the URL property so graphic provider is able to load the image
+ Set vMediaProperties = Array(ScriptForge.SF_Utils._MakePropertyValue(&quot;URL&quot;, psURL))
+
+ &apos; Retrieve the com.sun.star.graphic.XGraphic instance
+ Set oImage = oGraphicProvider.queryGraphic(vMediaProperties)
+
+Finally:
+ Set _GetImageFromUrl = oImage
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_PopupMenu._GetImageFromUrl
+
+REM -----------------------------------------------------------------------------
+Private Function _GetPopupMenu(ByVal psSubmenu As String) As Object
+&apos;&apos;&apos; Get the com.sun.star.awt.XPopupMenu object corresponding with the string in argument
+&apos;&apos;&apos; If the menu exists, it is found in the MenuTree dictionary
+&apos;&apos;&apos; If it does not exist, it is created recursively.
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psSubmenu: a string like &quot;A&gt;B&quot;
+&apos;&apos;&apos; Returns
+&apos;&apos;&apos; A com.sun.star.awt.XpopupMenu object
+&apos;&apos;&apos; Example
+&apos;&apos;&apos; If psSubmenu = &quot;A&gt;B&gt;C&gt;D&quot;, and only the root menu exists,
+&apos;&apos;&apos; - &quot;A&quot;, &quot;A&gt;B&quot;, &quot;A&gt;B&gt;C&quot;, &quot;A&gt;B&gt;C&gt;D&quot; should be created
+&apos;&apos;&apos; - the popup menu corresponding with &quot;A&gt;B&gt;C&gt;D&quot; should be returned
+
+Dim oPopup As Object &apos; Return value
+Dim vSplit As Variant &apos; An array as returned by _SplitMenuItem()
+Dim sMenu As String &apos; The left part of psSubmenu
+Dim oMenu As Object &apos; com.sun.star.awt.XpopupMenu
+Dim oLastMenu As Object &apos; com.sun.star.awt.XpopupMenu
+Dim i As Long
+
+ Set oPopup = Nothing
+ Set oLastMenu = MenuRoot
+Try:
+ If Len(psSubmenu) = 0 Then &apos; Menu starts at the root
+ Set oPopup = MenuRoot
+ ElseIf MenuTree.Exists(psSubmenu) Then &apos; Shortcut: if the submenu exists, get it directly
+ Set oPopup = MenuTree.Item(psSubmenu)
+ Else &apos; Build the tree
+ vSplit = Split(psSubmenu, SubmenuChar)
+ &apos; Search the successive submenus in the MenuTree dictionary, If not found, create a new entry
+ For i = 0 To UBound(vSplit)
+ sMenu = Join(ScriptForge.SF_Array.Slice(vSplit, 0, i), SubmenuChar)
+ If MenuTree.Exists(sMenu) Then
+ Set oLastMenu = MenuTree.Item(sMenu)
+ Else
+ &apos; Insert the new menu tree item
+ LastItem = LastItem + 1
+ oLastMenu.insertItem(LastItem, vSplit(i), 0, -1)
+ Set oMenu = CreateUnoService(&quot;stardiv.vcl.PopupMenu&quot;)
+ If MenubarMenu Then SFWidgets.SF_MenuListener.SetMenuListener(oMenu)
+ MenuTree.Add(sMenu, oMenu)
+ oLastMenu.setPopupMenu(LastItem, oMenu)
+ Set oLastMenu = oMenu
+ End If
+ Next i
+ Set oPopup = oLastMenu
+ End If
+
+Finally:
+ Set _GetPopupMenu = oPopup
+ Exit Function
+End Function &apos; SFWidgets.SF_PopupMenu._GetPopupMenu
+
+REM -----------------------------------------------------------------------------
+Public Sub _Initialize(ByRef poPeer As Object _
+ , plXPos As Long _
+ , plYPos As Long _
+ , psSubmenuChar As String _
+ )
+&apos;&apos;&apos; Complete the object creation process:
+&apos;&apos;&apos; - Initialize the dictionaries
+&apos;&apos;&apos; - initialize the root popup menu
+&apos;&apos;&apos; - initialize the display area
+&apos;&apos;&apos; - store the arguments for later use
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; poPeer: a peer window
+&apos;&apos;&apos; plXPos, plYPos: the coordinates
+
+Try:
+ &apos; Initialize the dictionaries
+ With ScriptForge.SF_Services
+ Set MenuTree = .CreateScriptService(&quot;Dictionary&quot;)
+ Set MenuIdentification = .CreateScriptService(&quot;Dictionary&quot;)
+ End With
+
+ &apos; Initialize the root of the menu tree
+ Set MenuRoot = CreateUnoService(&quot;stardiv.vcl.PopupMenu&quot;)
+
+ &apos; Setup the display area
+ Set Rectangle = New com.sun.star.awt.Rectangle
+ Rectangle.X = plXPos
+ Rectangle.Y = plYPos
+
+ &apos; Keep the targeted window
+ Set PeerWindow = poPeer
+
+ &apos; Store the submenu character
+ If Len(psSubmenuChar) &gt; 0 Then SubmenuChar = psSubmenuChar
+
+Finally:
+ Exit Sub
+End Sub &apos; SFWidgets.SF_PopupMenu._Initialize
+
+REM -----------------------------------------------------------------------------
+Private Function _PropertyGet(Optional ByVal psProperty As String) As Variant
+&apos;&apos;&apos; Return the value of the named property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psProperty: the name of the property
+
+Dim vGet As Variant &apos; Return value
+Dim cstThisSub As String
+Const cstSubArgs = &quot;&quot;
+
+ cstThisSub = &quot;SFWidgets.PopupMenu.get&quot; &amp; psProperty
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+ ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+ _PropertyGet = Null
+
+ Select Case UCase(psProperty)
+ Case UCase(&quot;ShortcutCharacter&quot;)
+ _PropertyGet = _UnderlineAccessKeyChar
+ Case UCase(&quot;SubmenuCharacter&quot;)
+ _PropertyGet = SubmenuChar
+ Case Else
+ _PropertyGet = Null
+ End Select
+
+Finally:
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_PopupMenu._PropertyGet
+
+REM -----------------------------------------------------------------------------
+Private Function _Repr() As String
+&apos;&apos;&apos; Convert the SF_PopupMenu instance to a readable string, typically for debugging purposes (DebugPrint ...)
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Return:
+&apos;&apos;&apos; &quot;[PopupMenu]: Name, Type (dialogname)
+ _Repr = &quot;[PopupMenu]: &quot; &amp; SF_String.Represent(MenuTree.Keys()) &amp; &quot;, &quot; &amp; SF_String.Represent(MenuIdentification.Items())
+
+End Function &apos; SFWidgets.SF_PopupMenu._Repr
+
+REM -----------------------------------------------------------------------------
+Private Function _SplitMenuItem(ByVal psMenuItem As String ) As Variant
+&apos;&apos;&apos; Split a menu item given as a string and delimited by the submenu character
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psMenuItem: a string like &quot;A&gt;B&gt;C&quot;
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; An array: [0] = &quot;A&gt;B&quot;
+&apos;&apos;&apos; [1] = &quot;C&quot;
+
+Dim vReturn(0 To 1) As String &apos; Return value
+Dim vMenus() As Variant &apos; Array of menus
+
+Try:
+ vMenus = Split(psMenuItem, SubmenuChar)
+ vReturn(1) = vMenus(UBound(vMenus))
+ vReturn(0) = Left(psMenuItem, Len(psMenuItem) - Iif(UBound(vMenus) &gt; 0, Len(SubmenuChar), 0) - Len(vReturn(1)))
+
+Finally:
+ _SplitMenuItem = vReturn
+End Function &apos; SFWidgets.SF_PopupMenu._SplitMenuItem
+
+REM ============================================ END OF SFWIDGETS.SF_POPUPMENU
+</script:module> \ No newline at end of file
diff --git a/wizards/source/sfwidgets/SF_Register.xba b/wizards/source/sfwidgets/SF_Register.xba
new file mode 100644
index 0000000000..d2c4245131
--- /dev/null
+++ b/wizards/source/sfwidgets/SF_Register.xba
@@ -0,0 +1,257 @@
+<?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 SFWidgets 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; - _NewMenu
+&apos;&apos;&apos; Create a new menu service instance.
+&apos;&apos;&apos; Called from SFDocuments services with CreateMenu()
+&apos;&apos;&apos; - _NewPopupMenu
+&apos;&apos;&apos; Create a new popup menu service instance.
+&apos;&apos;&apos; Called from CreateScriptService()
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&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
+
+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;Menu&quot;, &quot;SFWidgets.SF_Register._NewMenu&quot;) &apos; Reference to the function initializing the service
+ .RegisterService(&quot;PopupMenu&quot;, &quot;SFWidgets.SF_Register._NewPopupMenu&quot;) &apos; id.
+ .RegisterService(&quot;Toolbar&quot;, &quot;SFWidgets.SF_Register._NewToolbar&quot;) &apos; id.
+ .RegisterService(&quot;ToolbarButton&quot;, &quot;SFWidgets.SF_Register._NewToolbarButton&quot;) &apos; id.
+ End With
+
+End Sub &apos; SFWidgets.SF_Register.RegisterScriptServices
+
+REM =========================================================== PRIVATE FUNCTIONS
+
+REM -----------------------------------------------------------------------------
+Public Function _NewMenu(Optional ByVal pvArgs As Variant) As Object
+&apos;&apos;&apos; Create a new instance of the SF_Menu class
+&apos;&apos;&apos; [called internally from SFDocuments.Document.CreateMenu() ONLY]
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Component: the com.sun.star.lang.XComponent where to find the menubar to plug the new menu in
+&apos;&apos;&apos; Header: the name/header of the menu
+&apos;&apos;&apos; Before: the place where to put the new menu on the menubar (string or number &gt;= 1)
+&apos;&apos;&apos; When not found =&gt; last position
+&apos;&apos;&apos; SubmenuChar: the delimiter used in menu trees. Default = &quot;&gt;&quot;
+&apos;&apos;&apos; Returns: the instance or Nothing
+
+Dim oMenu As Object &apos; Return value
+Dim oComponent As Object &apos; The document or formdocument&apos;s component - com.sun.star.lang.XComponent
+Dim sHeader As String &apos; Menu header
+Dim sBefore As String &apos; Position of menu as a string
+Dim iBefore As Integer &apos; as a number
+Dim sSubmenuChar As String &apos; Delimiter in menu trees
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ Set oMenu = Nothing
+
+Check:
+ &apos; Types and number of arguments are not checked because internal call only
+ Set oComponent = pvArgs(0)
+ sHeader = pvArgs(1)
+ Select Case VarType(pvArgs(2))
+ Case V_STRING : sBefore = pvArgs(2)
+ iBefore = 0
+ Case Else : sBefore = &quot;&quot;
+ iBefore = pvArgs(2)
+ End Select
+ sSubmenuChar = pvArgs(3)
+
+Try:
+ If Not IsNull(oComponent) Then
+ Set oMenu = New SF_Menu
+ With oMenu
+ Set .[Me] = oMenu
+ ._Initialize(oComponent, sHeader, sBefore, iBefore, sSubmenuChar)
+ End With
+ End If
+
+Finally:
+ Set _NewMenu = oMenu
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_Register._NewMenu
+
+REM -----------------------------------------------------------------------------
+Public Function _NewPopupMenu(Optional ByVal pvArgs As Variant) As Object
+&apos;&apos;&apos; Create a new instance of the SF_PopupMenu class
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Event: a mouse event
+&apos;&apos;&apos; If the event has no source or is not a mouse event, the menu is displayed above the actual window
+&apos;&apos;&apos; X, Y: forced coordinates
+&apos;&apos;&apos; SubmenuChar: Delimiter used in menu trees
+&apos;&apos;&apos; Returns: the instance or Nothing
+
+Dim oMenu As Object &apos; Return value
+Dim Event As Variant &apos; Mouse event
+Dim X As Long &apos; Mouse click coordinates
+Dim Y As Long
+Dim SubmenuChar As String &apos; Delimiter in menu trees
+Dim vUno As Variant &apos; UNO type split into an array
+Dim sEventType As String &apos; Event type, must be &quot;MouseEvent&quot;
+Dim oControl As Object &apos; The dialog or form control view which triggered the event
+Dim oWindow As Object &apos; ui.Window type
+Dim oSession As Object : Set oSession = ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.Session&quot;)
+Dim oUi As Object : Set oUi = ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.UI&quot;)
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ Set oMenu = Nothing
+
+Check:
+ &apos; Check and get arguments, their number may vary
+ If IsMissing(pvArgs) Or IsEmpty(pvArgs) Then pvArgs = Array()
+ If Not IsArray(pvArgs) Then pvArgs = Array(pvArgs)
+ If UBound(pvArgs) &gt;= 0 Then Event = pvArgs(0) Else Event = Nothing
+ If IsEmpty(Event) Then Event = Nothing
+ If UBound(pvArgs) &gt;= 1 Then X = pvArgs(1) Else X = 0
+ If UBound(pvArgs) &gt;= 2 Then Y = pvArgs(2) Else Y = 0
+ If UBound(pvArgs) &gt;= 3 Then SubmenuChar = pvArgs(3) Else SubmenuChar = &quot;&quot;
+ If Not ScriptForge.SF_Utils._Validate(Event, &quot;Event&quot;, ScriptForge.V_OBJECT) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(X, &quot;X&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(Y, &quot;Y&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(SubmenuChar, &quot;SubmenuChar&quot;, V_STRING) Then GoTo Finally
+
+Try:
+ &apos; Find and identify the control that triggered the popup menu
+ Set oControl = Nothing
+ If Not IsNull(Event) Then
+ &apos; Determine the X, Y coordinates
+ vUno = Split(oSession.UnoObjectType(Event), &quot;.&quot;)
+ sEventType = vUno(UBound(vUno))
+ If UCase(sEventType) = &quot;MOUSEEVENT&quot; Then
+ X = Event.X
+ Y = Event.Y
+ &apos; Determine the window peer target
+ If oSession.HasUnoProperty(Event, &quot;Source&quot;) Then Set oControl = Event.Source.Peer
+ End If
+ End If
+ &apos; If not a mouse event, if no control, find what can be decent alternatives: (a menu header in) the actual window
+ If IsNull(oControl) Then
+ Set oWindow = oUi._IdentifyWindow(StarDesktop.getCurrentComponent()) &apos; A menu has been clicked necessarily in the current window
+ With oWindow
+ If Not IsNull(.Frame) Then Set oControl = .Frame.getContainerWindow()
+ End With
+ End If
+
+ If Not IsNull(oControl) Then
+ Set oMenu = New SF_PopupMenu
+ With oMenu
+ Set .[Me] = oMenu
+ ._Initialize(oControl, X, Y, SubmenuChar)
+ End With
+ Else
+ Set oMenu = Nothing
+ End If
+
+Finally:
+ Set _NewPopupMenu = oMenu
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_Register._NewPopupMenu
+
+REM -----------------------------------------------------------------------------
+Public Function _NewToolbar(Optional ByVal pvArgs As Variant) As Object
+&apos;&apos;&apos; Create a new instance of the SF_Toolbar class
+&apos;&apos;&apos; The &quot;Toolbar&quot; service must not be invoked directly in a user script
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; ToolbarDesc: a proto-toolbar object type. See ScriptForge.SF_UI for a detailed description
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; the instance or Nothing
+
+Dim oToolbar As Object &apos; Return value
+Dim oToolbarDesc As Object &apos; A proto-toolbar description
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ Set oToolbar = Nothing
+
+Check:
+ Set oToolbarDesc = pvArgs(0)
+
+Try:
+ Set oToolbar = New SF_Toolbar
+ With oToolbar
+ Set .[Me] = oToolbar
+ ._Initialize(oToolbarDesc)
+ End With
+
+Finally:
+ Set _NewToolbar = oToolbar
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_Register._NewToolbar
+
+REM -----------------------------------------------------------------------------
+Public Function _NewToolbarButton(Optional ByVal pvArgs As Variant) As Object
+&apos;&apos;&apos; Create a new instance of the SF_ToolbarButton class
+&apos;&apos;&apos; The &quot;ToolbarButton&quot; service must not be invoked directly in a user script
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; ToolbarButtonDesc: a proto-toolbarButton object type. See SFWidgets.SF_Toolbar for a detailed description
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; the instance or Nothing
+
+Dim oToolbarButton As Object &apos; Return value
+Dim oToolbarButtonDesc As Object &apos; A proto-toolbarbutton description
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ Set oToolbarButton = Nothing
+
+Check:
+ Set oToolbarButtonDesc = pvArgs(0)
+
+Try:
+ Set oToolbarButton = New SF_ToolbarButton
+ With oToolbarButton
+ Set .[Me] = oToolbarButton
+ ._Initialize(oToolbarButtonDesc)
+ End With
+
+Finally:
+ Set _NewToolbarButton = oToolbarButton
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_Register._NewToolbarButton
+
+
+REM ============================================== END OF SFWIDGETS.SF_REGISTER
+</script:module> \ No newline at end of file
diff --git a/wizards/source/sfwidgets/SF_Toolbar.xba b/wizards/source/sfwidgets/SF_Toolbar.xba
new file mode 100644
index 0000000000..c457a62f1c
--- /dev/null
+++ b/wizards/source/sfwidgets/SF_Toolbar.xba
@@ -0,0 +1,541 @@
+<?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_Toolbar" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
+REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
+REM === The SFWidgets 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_Toolbar
+&apos;&apos;&apos; ==========
+&apos;&apos;&apos; Hide/show a toolbar related to a component/document.
+&apos;&apos;&apos;
+&apos;&apos;&apos; Each component has its own set of toolbars, depending on the component type
+&apos;&apos;&apos; (Calc, Writer, Basic IDE, ...).
+&apos;&apos;&apos; In the context of the actual class, a toolbar is presumed defined statically:
+&apos;&apos;&apos; - either by the application
+&apos;&apos;&apos; - or by a customization done by the user.
+&apos;&apos;&apos; The definition of a toolbar can be stored in the application configuration files
+&apos;&apos;&apos; or in a specific document.
+&apos;&apos;&apos; Changes made by scripts to toolbars stored in the application are persistent.
+&apos;&apos;&apos; They are valid for all documents of the same type.
+&apos;&apos;&apos;
+&apos;&apos;&apos; Note that the menubar and the statusbar are not considered toolbars in this context.
+&apos;&apos;&apos;
+&apos;&apos;&apos; A toolbar consists in a series of graphical controls to trigger actions.
+&apos;&apos;&apos; The &quot;Toolbar&quot; service gives access to the &quot;ToolbarButton&quot; service to manage
+&apos;&apos;&apos; the individual buttons belonging to the toolbar.
+&apos;&apos;&apos;
+&apos;&apos;&apos; The name of a toolbar is either:
+&apos;&apos;&apos; - its so-called UIName when it is available,
+&apos;&apos;&apos; - or the last component of the resource URL: &quot;private:resource/toolbar/the-name-here&quot;
+&apos;&apos;&apos;
+&apos;&apos;&apos; Service invocation:
+&apos;&apos;&apos; The Toolbars() method returns the list of available toolbar names
+&apos;&apos;&apos; The Toolbars(toolbarname) returns a Toolbar service
+&apos;&apos;&apos; It is available from
+&apos;&apos;&apos; - the UI service to access the toolbars of the Basic IDE (&quot;BASICIDE&quot;),
+&apos;&apos;&apos; the start center (&quot;WELCOMESCREEN&quot;) or the active window
+&apos;&apos;&apos; - the Document, Calc, Writer, Datasheet, FormDocument services to access
+&apos;&apos;&apos; their respective set of toolbars.
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Dim oCalc As Object, oToolbar As Object
+&apos;&apos;&apos; Set oCalc = CreateScriptService(&quot;Calc&quot;, &quot;myFile.ods&quot;)
+&apos;&apos;&apos; Set oToolbar = oCalc.Toolbars(&quot;findbar&quot;)
+
+REM ================================================================== EXCEPTIONS
+
+REM ============================================================= PRIVATE MEMBERS
+
+Private [Me] As Object
+Private ObjectType As String &apos; Must be TOOLBAR
+Private ServiceName As String
+
+Private _Component As Object &apos; com.sun.star.lang.XComponent
+Private _ResourceURL As String &apos; Toolbar internal name
+Private _UIName As String &apos; Toolbar external name, may be &quot;&quot;
+Private _UIConfigurationManager As Object &apos; com.sun.star.ui.XUIConfigurationManager
+Private _ElementsInfoIndex As Long &apos; Index of the toolbar in the getElementsInfo(0) array
+Private _Storage As Long &apos; One of the toolbar location constants
+Private _LayoutManager As Object &apos; com.sun.star.comp.framework.LayoutManager
+
+Private _ToolbarButtons As Object &apos; SF_Dictionary of toolbar buttons
+
+Type _ToolbarButton
+ Toolbar As Object &apos; The actual SF_Toolbar object instance
+ Index As Long &apos; Entry number in buttons lists
+ Label As String &apos; Label (static description)
+ AccessibleName As String &apos; Name found in accessible context
+ Element As Object &apos; com.sun.star.ui.XUIElement
+End Type
+
+REM ============================================================ MODULE CONSTANTS
+
+&apos; Toolbar locations
+Private Const cstBUILTINTOOLBAR = 0 &apos; Standard toolbar
+Private Const cstCUSTOMTOOLBAR = 1 &apos; Toolbar added by user and stored in the LibreOffice application
+Private Const cstCUSTOMDOCTOOLBAR = 2 &apos; Toolbar added by user solely for a single document
+
+REM ====================================================== CONSTRUCTOR/DESTRUCTOR
+
+REM -----------------------------------------------------------------------------
+Private Sub Class_Initialize()
+ Set [Me] = Nothing
+ ObjectType = &quot;TOOLBAR&quot;
+ ServiceName = &quot;SFWidgets.Toolbar&quot;
+ Set _Component = Nothing
+ _ResourceURL = &quot;&quot;
+ _UIName = &quot;&quot;
+ Set _UIConfigurationManager = Nothing
+ _ElementsInfoIndex = -1
+ _Storage = 0
+ Set _LayoutManager = Nothing
+ Set _ToolbarButtons = Nothing
+End Sub &apos; SFWidgets.SF_Toolbar Constructor
+
+REM -----------------------------------------------------------------------------
+Private Sub Class_Terminate()
+ Call Class_Initialize()
+End Sub &apos; SFWidgets.SF_Toolbar Destructor
+
+REM -----------------------------------------------------------------------------
+Public Function Dispose() As Variant
+ Call Class_Terminate()
+ Set Dispose = Nothing
+End Function &apos; SFWidgets.SF_Toolbar Explicit Destructor
+
+REM ================================================================== PROPERTIES
+
+REM -----------------------------------------------------------------------------
+Property Get BuiltIn() As Boolean
+&apos;&apos;&apos; Returns True when the toolbar is part of the set of standard toolbars shipped with the application.
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myToolbar.BuiltIn
+
+ BuiltIn = _PropertyGet(&quot;BuiltIn&quot;)
+
+End Property &apos; SFWidgets.SF_Toolbar.BuiltIn (get)
+
+REM -----------------------------------------------------------------------------
+Property Get Docked() As Variant
+&apos;&apos;&apos; Returns True when the toolbar is active in the window and Docked.
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myToolbar.Docked
+
+ Docked = _PropertyGet(&quot;Docked&quot;)
+
+End Property &apos; SFWidgets.SF_Toolbar.Docked (get)
+
+REM -----------------------------------------------------------------------------
+Property Get HasGlobalScope() As Boolean
+&apos;&apos;&apos; Returns True when the toolbar is available in all documents of the same type
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myToolbar.HasGlobalScope
+
+ HasGlobalScope = _PropertyGet(&quot;HasGlobalScope&quot;)
+
+End Property &apos; SFWidgets.SF_Toolbar.HasGlobalScope (get)
+
+REM -----------------------------------------------------------------------------
+Property Get Name() As String
+&apos;&apos;&apos; Returns the name of the toolbar
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myToolbar.Name
+
+ Name = _PropertyGet(&quot;Name&quot;)
+
+End Property &apos; SFWidgets.SF_Toolbar.Name (get)
+
+REM -----------------------------------------------------------------------------
+Property Get ResourceURL() As String
+&apos;&apos;&apos; Returns URL of the toolbar, in the form private:toolbar/xxx
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myToolbar.ResourceURL
+
+ ResourceURL = _PropertyGet(&quot;ResourceURL&quot;)
+
+End Property &apos; SFWidgets.SF_Toolbar.ResourceURL (get)
+
+REM -----------------------------------------------------------------------------
+Property Get Visible() As Variant
+&apos;&apos;&apos; Returns True when the toolbar is active in the window and visible.
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myToolbar.Visible
+
+ Visible = _PropertyGet(&quot;Visible&quot;)
+
+End Property &apos; SFWidgets.SF_Toolbar.Visible (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Visible(ByVal pvVisible As Variant)
+&apos;&apos;&apos; Sets the visible status of the toolbar.
+&apos;&apos;&apos; When the toolbar is not yet active i the window, it is first created.
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; myToolbar.Visible = True
+
+ _PropertySet(&quot;Visible&quot;, pvVisible)
+
+End Property &apos; SFWidgets.SF_Toolbar.Visible (let)
+
+REM -----------------------------------------------------------------------------
+Property Get XUIElement() As Variant
+&apos;&apos;&apos; Returns the com.sun.star.ui.XUIElement UNO object corresponding with the toolbar
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myToolbar.XUIElement
+
+ XUIElement = _PropertyGet(&quot;XUIElement&quot;)
+
+End Property &apos; SFWidgets.SF_Toolbar.XUIElement (get)
+
+REM ===================================================================== METHODS
+
+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; myToolbar.GetProperty(&quot;Visible&quot;)
+
+Const cstThisSub = &quot;SFWidgets.Toolbar.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; SFWidgets.SF_Toolbar.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;ToolbarButtons&quot; _
+ )
+
+End Function &apos; SFWidgets.SF_Toolbar.Methods
+
+REM -----------------------------------------------------------------------------
+Public Function Properties() As Variant
+&apos;&apos;&apos; Return the list or properties of the Timer a.AddItem(&quot;B&gt;B1&quot;)class as an array
+
+ Properties = Array( _
+ &quot;BuiltIn&quot; _
+ , &quot;Docked&quot; _
+ , &quot;HasGlobalScope&quot; _
+ , &quot;Name&quot; _
+ , &quot;ResourceURL&quot; _
+ , &quot;Visible&quot; _
+ , &quot;XUIElement&quot; _
+ )
+
+End Function &apos; SFWidgets.SF_Toolbar.Properties
+
+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;SFWidgets.Toolbar.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; SFWidgets.SF_Toolbar.SetProperty
+
+REM -----------------------------------------------------------------------------
+Public Function ToolbarButtons(Optional ByVal ButtonName As Variant) As Variant
+&apos;&apos;&apos; Returns either a list of the available toolbar button names in the actual toolbar
+&apos;&apos;&apos; or a ToolbarButton object instance.
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; ButtonName: the usual name of one of the available buttons in the actual toolbar
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; A zero-based array of button names when the argument is absent,
+&apos;&apos;&apos; or a new ToolbarButton object instance.
+&apos;&apos;&apos; An inactive toolbar has no buttons =&gt; the actual method forces the toolbar to be made visible first.
+
+Const cstThisSub = &quot;SFWidgets.Toolbar.ToolbarButtons&quot;
+Const cstSubArgs = &quot;[ButtonName=&quot;&quot;&quot;&quot;]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+Check:
+ If IsMissing(ButtonName) Or IsEmpty(ButtonName) Then ButtonName = &quot;&quot;
+ &apos; Store button descriptions in cache
+ _CollectAllButtons()
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If VarType(ButtonName) = V_STRING Then
+ If Len(ButtonName) &gt; 0 Then
+ If Not ScriptForge.SF_Utils._Validate(ButtonName, &quot;ButtonName&quot;, V_STRING, _ToolbarButtons.Keys()) Then GoTo Finally
+ End If
+ Else
+ If Not ScriptForge.SF_Utils._Validate(ButtonName, &quot;ButtonName&quot;, V_STRING) Then GoTo Finally &apos; Manage here the VarType error
+ End If
+ End If
+
+Try:
+ If Len(ButtonName) = 0 Then
+ ToolbarButtons = _ToolbarButtons.Keys()
+ Else
+ ToolbarButtons = CreateScriptService(&quot;SFWidgets.ToolbarButton&quot;, _ToolbarButtons.Item(ButtonName))
+ End If
+
+Finally:
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_Toolbar.ToolbarButtons
+
+REM =========================================================== PRIVATE FUNCTIONS
+
+REM -----------------------------------------------------------------------------
+Private Sub _CollectAllButtons()
+&apos;&apos;&apos; Stores a SF_Dictionary object instance, with
+&apos;&apos;&apos; - key = name of the button
+&apos;&apos;&apos; - item = a _ButtonDesc object type
+&apos;&apos;&apos; into _ToolbarButtons, a cache for all buttons.
+&apos;&apos;&apos; The toolbar is made visible before collecting the buttons.
+&apos;&apos;&apos;
+&apos;&apos;&apos; The name of the buttons is derived either from:
+&apos;&apos;&apos; - the Label property of the static toolbar and toolbar buttons definitions
+&apos;&apos;&apos; - or the AccessibleName property of the AccessibleContext of the button
+&apos;&apos;&apos; whichever is found first.
+&apos;&apos;&apos; Separators are skipped.
+&apos;&apos;&apos; If there are homonyms (&gt;= 2 buttons having the same name), only the 1st one is retained.
+
+Dim oElement As Object &apos; com.sun.star.ui.XUIElement
+Dim oSettings As Object &apos; com.sun.star.container.XIndexAccess
+Dim vProperties() As Variant &apos; Array of property values
+Dim iType As Integer &apos; Separators have type = 1, others have Type = 0
+Dim oAccessible As Object &apos; com.sun.star.accessibility.XAccessible
+Dim sLabel As String &apos; Label in static description
+Dim sAccessibleName As String &apos; Name in AccessibleContext
+Dim sButtonName As String &apos; Key part in dictionary entry
+Dim oButton As Object &apos; Item part in dictionary entry
+Dim i As Long
+
+ On Local Error GoTo Catch
+ If Not IsNull(_ToolbarButtons) Then GoTo Finally &apos; Do not redo the job if already done
+
+Try:
+ &apos; Force the visibility of the toolbar
+ Visible = True
+
+ Set _ToolbarButtons = ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.Dictionary&quot;)
+ Set oElement = _LayoutManager.getElement(_ResourceURL)
+ Set oSettings = oElement.getSettings(True)
+
+ With oSettings
+ For i = 0 To .Count - 1
+ vProperties = .getByIndex(i)
+ iType = ScriptForge.SF_Utils._GetPropertyValue(vProperties, &quot;Type&quot;)
+ If iType = 0 Then &apos; Usual button
+ sLabel = ScriptForge.SF_Utils._GetPropertyValue(vProperties, &quot;Label&quot;)
+ If Len(sLabel) = 0 Then
+ Set oAccessible = oElement.RealInterface.AccessibleContext.getAccessibleChild(i)
+ sAccessibleName = oAccessible.AccessibleName
+ Else
+ sAccessibleName = &quot;&quot;
+ End If
+ &apos; Store in dictionary
+ sButtonName = sLabel &amp; sAccessibleName &apos; At least 1 of them is blank
+ If Len(sButtonName) &gt; 0 Then
+ Set oButton = New _ToolbarButton
+ With oButton
+ Set .Toolbar = [Me]
+ .Index = i
+ .Label = sLabel
+ .AccessibleName = sAccessibleName
+ Set .Element = oElement
+ End With
+ With _ToolbarButtons
+ If Not .Exists(sButtonName) Then .Add(sButtonName, oButton)
+ End With
+ End If
+ End If
+ Next i
+ End With
+
+Finally:
+ Exit Sub
+Catch:
+ &apos; _ToolbarButtons is left unchanged
+ GoTo Finally
+End Sub &apos; SFWidgets.SF_Toolbar._CollectAllButtons
+
+REM -----------------------------------------------------------------------------
+Public Sub _Initialize(ByRef poToolbar As Object)
+&apos;&apos;&apos; Complete the object creation process:
+&apos;&apos;&apos; - Initialize the toolbar descriptioner use
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; poToolbar: the toolbar description as a ui._Toolbr object
+
+Try:
+ &apos; Store the static description
+ With poToolbar
+ _Component = .Component
+ _ResourceURL = .ResourceURL
+ _UIName = .UIName
+ _UIConfigurationManager = .UIConfigurationManager
+ _ElementsInfoIndex = .ElementsInfoIndex
+ _Storage = .Storage
+ End With
+
+ &apos; Complement
+ If Len(_UIName) = 0 Then _UIName = Split(_ResourceURL, &quot;/&quot;)(2)
+ Set _LayoutManager = _Component.CurrentController.Frame.LayoutManager
+
+Finally:
+ Exit Sub
+End Sub &apos; SFWidgets.SF_Toolbar._Initialize
+
+REM -----------------------------------------------------------------------------
+Private Function _PropertyGet(Optional ByVal psProperty As String) As Variant
+&apos;&apos;&apos; Return the value of the named property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psProperty: the name of the property
+
+Dim vGet As Variant &apos; Return value
+Dim oElement As Object &apos; com.sun.star.ui.XUIElement
+Dim cstThisSub As String
+Const cstSubArgs = &quot;&quot;
+
+ cstThisSub = &quot;SFWidgets.Toolbar.get&quot; &amp; psProperty
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+ ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+ _PropertyGet = Null
+
+ Select Case UCase(psProperty)
+ Case UCase(&quot;BuiltIn&quot;)
+ _PropertyGet = ( _Storage = cstBUILTINTOOLBAR )
+ Case UCase(&quot;Docked&quot;)
+ Set oElement = _LayoutManager.getElement(_ResourceURL)
+ If Not IsNull(oElement) Then _PropertyGet = _LayoutManager.isElementDocked(_ResourceURL) Else _PropertyGet = False
+ Case UCase(&quot;HasGlobalScope&quot;)
+ _PropertyGet = ( _Storage = cstBUILTINTOOLBAR Or _Storage = cstCUSTOMTOOLBAR )
+ Case UCase(&quot;Name&quot;)
+ _PropertyGet = _UIName
+ Case UCase(&quot;ResourceURL&quot;)
+ _PropertyGet = _ResourceURL
+ Case UCase(&quot;Visible&quot;)
+ Set oElement = _LayoutManager.getElement(_ResourceURL)
+ If Not IsNull(oElement) Then _PropertyGet = _LayoutManager.isElementVisible(_ResourceURL) Else _PropertyGet = False
+ Case UCase(&quot;XUIElement&quot;)
+ _PropertyGet = _LayoutManager.getElement(_ResourceURL)
+ Case Else
+ _PropertyGet = Null
+ End Select
+
+Finally:
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_Toolbar._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
+Dim oElement As Object &apos; com.sun.star.ui.XUIElement
+Dim bVisible As Boolean &apos; Actual Visible state
+
+Dim cstThisSub As String
+Const cstSubArgs = &quot;Value&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bSet = False
+
+ cstThisSub = &quot;SFWidgets.Toolbar.set&quot; &amp; psProperty
+ ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+
+ bSet = True
+ Select Case UCase(psProperty)
+ Case UCase(&quot;Visible&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, ScriptForge.V_BOOLEAN) Then GoTo Catch
+ With _LayoutManager
+ Set oElement = .getElement(_ResourceURL)
+ If Not IsNull(oElement) Then bVisible = .isElementVisible(_ResourceURL) Else bVisible = False
+ &apos; If there is no change, do nothing
+ If Not bVisible = pvValue Then
+ If IsNull(oElement) And pvValue Then .createElement(_ResourceURL)
+ If pvValue Then .showElement(_ResourceURL) Else .hideElement(_ResourceURL)
+ End If
+ End With
+ Case Else
+ bSet = False
+ End Select
+
+Finally:
+ _PropertySet = bSet
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ bSet = False
+ GoTo Finally
+End Function &apos; SFWidgets.SF_Toolbar._PropertySet
+
+REM -----------------------------------------------------------------------------
+Private Function _Repr() As String
+&apos;&apos;&apos; Convert the SF_Toolbar instance to a readable string, typically for debugging purposes (DebugPrint ...)
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Return:
+&apos;&apos;&apos; &quot;[Toolbar]: Name, Type (dialogname)
+ _Repr = &quot;[Toolbar]: &quot; &amp; _UIName &amp; &quot; - &quot; &amp; _ResourceURL
+
+End Function &apos; SFWidgets.SF_Toolbar._Repr
+
+REM ============================================ END OF SFWIDGETS.SF_TOOLBAR
+</script:module> \ No newline at end of file
diff --git a/wizards/source/sfwidgets/SF_ToolbarButton.xba b/wizards/source/sfwidgets/SF_ToolbarButton.xba
new file mode 100644
index 0000000000..58c594f066
--- /dev/null
+++ b/wizards/source/sfwidgets/SF_ToolbarButton.xba
@@ -0,0 +1,565 @@
+<?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_ToolbarButton" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
+REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
+REM === The SFWidgets 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_ToolbarButton
+&apos;&apos;&apos; ================
+&apos;&apos;&apos; Hide/show toolbar elements, read and update their current behaviour..
+&apos;&apos;&apos;
+&apos;&apos;&apos; A toolbar consists in a series of graphical controls to trigger actions.
+&apos;&apos;&apos; The &quot;Toolbar&quot; service gives access to the &quot;ToolbarButton&quot; service to manage
+&apos;&apos;&apos; the individual buttons belonging to the toolbar.
+&apos;&apos;&apos;
+&apos;&apos;&apos; Changes made by scripts to buttons belonging to toolbars stored in the application
+&apos;&apos;&apos; are persistent. They are valid for all documents of the same type.
+&apos;&apos;&apos;
+&apos;&apos;&apos; The name of a toolbar button is either:
+&apos;&apos;&apos; - in custom toolbars, a predefined name given at its creation,
+&apos;&apos;&apos; - in standard toolbars, a localized name as read in the Tools + Customize ... dialog box
+&apos;&apos;&apos;
+&apos;&apos;&apos; Service invocation:
+&apos;&apos;&apos; It is available only from an active Toolbar service.
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Dim oCalc As Object, oToolbar As Object, oToolbarButton As Object
+&apos;&apos;&apos; Set oCalc = CreateScriptService(&quot;Calc&quot;, &quot;myFile.ods&quot;)
+&apos;&apos;&apos; Set oToolbar = oCalc.Toolbars(&quot;findbar&quot;)
+&apos;&apos;&apos; Set oToolbarButton = oToolbar.ToolbarButtons(&quot;Find Next&quot;)
+
+REM ================================================================== EXCEPTIONS
+
+REM ============================================================= PRIVATE MEMBERS
+
+Private [Me] As Object
+Private ObjectType As String &apos; Must be TOOLBARBUTTON
+Private ServiceName As String
+Private [_Parent] As Object &apos; SF_Toolbar instance owning the button
+
+Private _Index As Long &apos; Entry number in buttons lists
+Private _Label As String &apos; Label (static description)
+Private _AccessibleName As String &apos; Name found in accessible context
+Private _Element As Object &apos; com.sun.star.ui.XUIElement
+
+Private _CommandURL As String &apos; Uno command or script
+
+Private _Height As Long &apos; Height may be cached
+Private _Width As Long &apos; Width may be cached
+
+REM ============================================================ MODULE CONSTANTS
+
+REM ====================================================== CONSTRUCTOR/DESTRUCTOR
+
+REM -----------------------------------------------------------------------------
+Private Sub Class_Initialize()
+ Set [Me] = Nothing
+ ObjectType = &quot;TOOLBARBUTTON&quot;
+ ServiceName = &quot;SFWidgets.ToolbarButton&quot;
+ Set [_Parent] = Nothing
+ _Index = -1
+ _Label = &quot;&quot;
+ _AccessibleName = &quot;&quot;
+ Set _Element = Nothing
+ _CommandURL = &quot;&quot;
+ _Height = 0
+ _Width = 0
+End Sub &apos; SFWidgets.SF_ToolbarButton Constructor
+
+REM -----------------------------------------------------------------------------
+Private Sub Class_Terminate()
+ Call Class_Initialize()
+End Sub &apos; SFWidgets.SF_ToolbarButton Destructor
+
+REM -----------------------------------------------------------------------------
+Public Function Dispose() As Variant
+ Call Class_Terminate()
+ Set Dispose = Nothing
+End Function &apos; SFWidgets.SF_ToolbarButton Explicit Destructor
+
+REM ================================================================== PROPERTIES
+
+REM -----------------------------------------------------------------------------
+Property Get Caption() As String
+&apos;&apos;&apos; Returns the name of the button
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myButton.Caption
+
+ Caption = _PropertyGet(&quot;Caption&quot;)
+
+End Property &apos; SFWidgets.SF_ToolbarButton.Caption (get)
+
+REM -----------------------------------------------------------------------------
+Property Get Height() As Long
+&apos;&apos;&apos; Returns the height in pixels of the button
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myButton.Height
+
+ Height = _PropertyGet(&quot;Height&quot;)
+
+End Property &apos; SFWidgets.SF_ToolbarButton.Height (get)
+
+REM -----------------------------------------------------------------------------
+Property Get Index() As Long
+&apos;&apos;&apos; Returns the index of the button
+&apos;&apos;&apos; - in the Settings (com.sun.star.container.XIndexAccess) of the parent toolbar
+&apos;&apos;&apos; - in the AccessibleContext (com.sun.star.comp.toolkit.AccessibleToolBox) of the parent toolbar
+&apos;&apos;&apos; Both should be identical: the range number of the button in the toolbar, hidden buttons and separators included.
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myButton.Index
+
+ Index = _PropertyGet(&quot;Index&quot;)
+
+End Property &apos; SFWidgets.SF_ToolbarButton.Index (get)
+
+REM -----------------------------------------------------------------------------
+Property Get OnClick() As Variant
+&apos;&apos;&apos; Returns the UNO command or the script (expressed in the scripting framework_URI notation) run when the button is clicked
+&apos;&apos;&apos; Read https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification
+&apos;&apos;&apos; Note that no event object is passed to the script.
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myButton.OnClick
+
+ OnClick = _PropertyGet(&quot;OnClick&quot;)
+
+End Property &apos; SFWidgets.SF_ToolbarButton.OnClick (get)
+
+REM -----------------------------------------------------------------------------
+Property Let OnClick(ByVal pvOnClick As Variant)
+&apos;&apos;&apos; Sets the UNO command or the script (expressed in the scripting framework_URI notation) to trigger when the button is clicked
+&apos;&apos;&apos; It is highly recommended to not modify standard buttons.
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; myButton.OnClick = &quot;.uno:About&quot;
+&apos;&apos;&apos; myButton.OnClick = &quot;vnd.sun.star.script:XrayTool._Main.Xray?language=Basic&amp;location=application&quot;
+
+ _PropertySet(&quot;OnClick&quot;, pvOnClick)
+
+End Property &apos; SFWidgets.SF_ToolbarButton.OnClick (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Parent() As Object
+&apos;&apos;&apos; Returns the parent toolbar as a SF_Toolbar object instance
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; Set oToolbar = myButton.Parent
+
+ Set Parent = _PropertyGet(&quot;Parent&quot;)
+
+End Property &apos; SFWidgets.SF_ToolbarButton.Parent (get)
+
+REM -----------------------------------------------------------------------------
+Property Get TipText() As Variant
+&apos;&apos;&apos; Specifies the text that appears in a screentip when you hold the mouse pointer over the button
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myButton.TipText
+
+ TipText = _PropertyGet(&quot;TipText&quot;)
+
+End Property &apos; SFWidgets.SF_ToolbarButton.TipText (get)
+
+REM -----------------------------------------------------------------------------
+Property Let TipText(ByVal pvTipText As Variant)
+&apos;&apos;&apos; Sets the screentip associated with the actual toolbar button
+&apos;&apos;&apos; It is highly recommended to not modify standard buttons.
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; myButton.TipText = &quot;Click here&quot;
+
+ _PropertySet(&quot;TipText&quot;, pvTipText)
+
+End Property &apos; SFWidgets.SF_ToolbarButton.TipText (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Visible() As Variant
+&apos;&apos;&apos; Returns True when the toolbar button is visible. Otherwise False.
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myButton.Visible
+
+ Visible = _PropertyGet(&quot;Visible&quot;)
+
+End Property &apos; SFWidgets.SF_ToolbarButton.Visible (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Visible(ByVal pvVisible As Variant)
+&apos;&apos;&apos; Sets the visible status of the toolbar button.
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; myButton.Visible = True
+
+ _PropertySet(&quot;Visible&quot;, pvVisible)
+
+End Property &apos; SFWidgets.SF_ToolbarButton.Visible (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Width() As Long
+&apos;&apos;&apos; Returns the width in pixels of the button
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myButton.Width
+
+ Width = _PropertyGet(&quot;Width&quot;)
+
+End Property &apos; SFWidgets.SF_ToolbarButton.Width (get)
+
+REM -----------------------------------------------------------------------------
+Property Get X() As Long
+&apos;&apos;&apos; Returns the X (horizontal) coordinate in pixels of the top-left corner of the button
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myButton.X
+
+ X = _PropertyGet(&quot;X&quot;)
+
+End Property &apos; SFWidgets.SF_ToolbarButton.X (get)
+
+REM -----------------------------------------------------------------------------
+Property Get Y() As Long
+&apos;&apos;&apos; Returns the Y (vertical) coordinate in pixels of the top-left corner of the button
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; MsgBox myButton.Y
+
+ Y = _PropertyGet(&quot;Y&quot;)
+
+End Property &apos; SFWidgets.SF_ToolbarButton.Y (get)
+
+REM ===================================================================== METHODS
+
+REM -----------------------------------------------------------------------------
+Public Function Execute() As Variant
+&apos;&apos;&apos; Execute the command stored in the toolbar button.
+&apos;&apos;&apos; The command can be a UNO command or a Basic/Python script (expressed in the scripting framework_URI notation)
+&apos;&apos;&apos; Read https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification
+&apos;&apos;&apos; No argument is passed to the script to execute.
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The output of the script or Null
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; result = myButton.Execute()
+
+Dim vResult As Variant &apos; Return value
+Dim sCommand As String &apos; Command associated with button
+Dim oFrame As Object &apos; com.sun.star.comp.framework.Frame
+Dim oDispatcher As Object &apos; com.sun.star.frame.DispatchHelper
+Dim vScript As Variant &apos; Split command in script/argument
+Dim oSession As Object : Set oSession = ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.Session&quot;)
+Dim oArgs() As new com.sun.star.beans.PropertyValue
+Const cstUnoPrefix = &quot;.uno:&quot;
+
+Const cstThisSub = &quot;SFWidgets.ToolbarButton.Execute&quot;
+Const cstSubArgs = &quot;&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ vResult = Null
+
+Check:
+ ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+
+Try:
+ sCommand = GetProperty(&quot;OnClick&quot;)
+ If Len(sCommand) &gt; 0 Then
+ &apos; A button has been clicked necessarily in the current window (Document) or one of its subcomponents (FormDocument)
+ Set oFrame = StarDesktop.ActiveFrame
+ If oFrame.Frames.Count &gt; 0 Then Set oFrame = oFrame.getActiveFrame()
+ &apos; Command or script ?
+ If ScriptForge.SF_String.StartsWith(sCommand, cstUnoPrefix) Then
+ &apos; Execute uno command
+ Set oDispatcher = ScriptForge.SF_Utils._GetUNOService(&quot;DispatchHelper&quot;)
+ oDispatcher.executeDispatch(oFrame, sCommand, &quot;&quot;, 0, oArgs())
+ oFrame.activate()
+ Else
+ &apos; Execute script
+ vResult = oSession._ExecuteScript(sCommand)
+ End If
+ End If
+
+Finally:
+ Execute = vResult
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_ToolbarButton.Execute
+
+REM -----------------------------------------------------------------------------
+Public Function GetProperty(Optional ByVal PropertyName As Variant) As Variant
+&apos;&apos;&apos; Return the actual value of the given property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; PropertyName: the name of the property as a string
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The actual value of the property
+&apos;&apos;&apos; 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; myToolbar.GetProperty(&quot;Visible&quot;)
+
+Const cstThisSub = &quot;SFWidgets.ToolbarButton.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; SFWidgets.SF_ToolbarButton.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;Execute&quot; _
+ )
+
+End Function &apos; SFWidgets.SF_ToolbarButton.Methods
+
+REM -----------------------------------------------------------------------------
+Public Function Properties() As Variant
+&apos;&apos;&apos; Return the list or properties of the Timer a.AddItem(&quot;B&gt;B1&quot;)class as an array
+
+ Properties = Array( _
+ &quot;Caption&quot; _
+ , &quot;Height&quot; _
+ , &quot;Index&quot; _
+ , &quot;OnClick&quot; _
+ , &quot;Parent&quot; _
+ , &quot;TipText&quot; _
+ , &quot;Visible&quot; _
+ , &quot;Width&quot; _
+ , &quot;X&quot; _
+ , &quot;Y&quot; _
+ )
+
+End Function &apos; SFWidgets.SF_ToolbarButton.Properties
+
+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;SFWidgets.ToolbarButton.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; SFWidgets.SF_ToolbarButton.SetProperty
+
+REM =========================================================== PRIVATE FUNCTIONS
+
+REM -----------------------------------------------------------------------------
+Private Function _GetPosition() As Object
+&apos;&apos;&apos; Determine the position of the top-left corner of the actual button.
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; a com.sun.star.awt.Rectangle structure
+
+Dim oElement As Object &apos; com.sun.star.ui.XUIElement
+Dim oAccessible As Object &apos; com.sun.star.comp.toolkit.AccessibleToolBoxItem
+Dim oAccessibleButton As Object &apos; com.sun.star.comp.toolkit.AccessibleToolBoxItem
+Dim oAccessibleParent As Object &apos; com.sun.star.comp.toolkit.AccessibleToolBoxItem
+Dim oRect As Object &apos; Return value As com.sun.star.awt.Rectangle
+
+Try:
+ Set oElement = _Element.GetSettings(True).getByIndex(_Index)
+ Set oRect = CreateUnoStruct(&quot;com.sun.star.awt.Rectangle&quot;)
+ If ScriptForge.SF_Utils._GetPropertyValue(oElement, &quot;IsVisible&quot;) Then
+ Set oAccessible = _Element.getRealInterface().getAccessibleContext() &apos; Toolbar level
+ Set oAccessibleParent = oAccessible.getAccessibleParent() &apos; Window level
+ Set oAccessibleButton = oAccessible.getAccessibleChild(_Index) &apos; Toolbar button level
+ &apos; The X and Y coordinates are always computed correctly when the toolbar is docked.
+ &apos; When the toolbar is floating, the Y ordinate may be overestimated with the height of
+ &apos; the tabbed bar or similar. However no mean has been found to get that height via code.
+ With oRect
+ .X = oAccessible.Location.X + oAccessibleButton.Location.X + oAccessibleParent.PosSize.X
+ .Y = oAccessible.Location.Y + oAccessibleButton.Location.Y + oAccessibleParent.PosSize.Y
+ .Height = oAccessibleButton.Size.Height
+ .Width = oAccessibleButton.Size.Width
+ End With
+ Else
+ With oRect
+ .X = -1 : .Y = -1 : .Height = 0 : .Width = 0
+ End With
+ End If
+
+Finally:
+ Set _GetPosition = oRect
+ Exit Function
+End Function &apos; SFWidgets.SF_ToolbarButton._GetPosition
+
+REM -----------------------------------------------------------------------------
+Public Sub _Initialize(ByRef poToolbarButton As Object)
+&apos;&apos;&apos; Complete the object creation process:
+&apos;&apos;&apos; - Initialize the toolbar descriptioner use
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; poToolbarButton: the toolbar description as a ui._Toolbr object
+
+Try:
+ &apos; Store the static description
+ With poToolbarButton
+ Set [_Parent] = .Toolbar
+ _Index = .Index
+ _Label = .Label
+ _AccessibleName = .AccessibleName
+ Set _Element = .Element
+ End With
+
+ &apos; Complement
+ _CommandURL = ScriptForge.SF_Utils._GetPropertyValue(_Element.getSettings(True).getByIndex(_Index), &quot;CommandURL&quot;)
+
+Finally:
+ Exit Sub
+End Sub &apos; SFWidgets.SF_ToolbarButton._Initialize
+
+REM -----------------------------------------------------------------------------
+Private Function _PropertyGet(Optional ByVal psProperty As String) As Variant
+&apos;&apos;&apos; Return the value of the named property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psProperty: the name of the property
+
+Dim vGet As Variant &apos; Return value
+Dim sTooltip As String &apos; ToolTip text
+Dim oElement As Object &apos; com.sun.star.ui.XUIElement
+Dim cstThisSub As String
+Const cstSubArgs = &quot;&quot;
+
+ cstThisSub = &quot;SFWidgets.ToolbarButton.get&quot; &amp; psProperty
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+ ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+ _PropertyGet = Null
+
+ Select Case UCase(psProperty)
+ Case UCase(&quot;Caption&quot;)
+ _PropertyGet = Iif(Len(_Label) &gt; 0, _Label, _AccessibleName)
+ Case UCase(&quot;Height&quot;)
+ If _Height &gt; 0 Then _PropertyGet = _Height else _PropertyGet = _GetPosition().Height
+ Case UCase(&quot;Index&quot;)
+ _PropertyGet = _Index
+ Case UCase(&quot;OnClick&quot;)
+ Set oElement = _Element.GetSettings(True).getByIndex(_Index)
+ _PropertyGet = ScriptForge.SF_Utils._GetPropertyValue(oElement, &quot;CommandURL&quot;)
+ Case UCase(&quot;Parent&quot;)
+ Set _PropertyGet = [_Parent]
+ Case UCase(&quot;TipText&quot;)
+ Set oElement = _Element.GetSettings(True).getByIndex(_Index)
+ sTooltip = ScriptForge.SF_Utils._GetPropertyValue(oElement, &quot;Tooltip&quot;)
+ If Len(sTooltip) &gt; 0 Then _PropertyGet = sTooltip Else _PropertyGet = Iif(Len(_Label) &gt; 0, _Label, _AccessibleName)
+ Case UCase(&quot;Visible&quot;)
+ Set oElement = _Element.GetSettings(True).getByIndex(_Index)
+ _PropertyGet = ScriptForge.SF_Utils._GetPropertyValue(oElement, &quot;IsVisible&quot;)
+ Case UCase(&quot;Width&quot;)
+ If _Width &gt; 0 Then _PropertyGet = _Width else _PropertyGet = _GetPosition().Width
+ Case UCase(&quot;X&quot;)
+ _PropertyGet = _GetPosition().X
+ Case UCase(&quot;Y&quot;)
+ _PropertyGet = _GetPosition().Y
+ Case Else
+ _PropertyGet = Null
+ End Select
+
+Finally:
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; SFWidgets.SF_ToolbarButton._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
+Dim oSettings As Object &apos; com.sun.star.container.XIndexAccess
+Dim vProperties As Variant &apos; Array of PropertyValues
+Dim bVisible As Boolean &apos; Actual Visible state
+
+Dim cstThisSub As String
+Const cstSubArgs = &quot;Value&quot;
+
+Check:
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bSet = False
+
+ cstThisSub = &quot;SFWidgets.ToolbarButton.set&quot; &amp; psProperty
+ ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+
+Try:
+ bSet = True
+ Set oSettings = _Element.getSettings(True)
+ vProperties = oSettings.getByIndex(_Index)
+
+ Select Case UCase(psProperty)
+ Case UCase(&quot;OnClick&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, V_STRING) Then GoTo Catch
+ ScriptForge.SF_Utils._SetPropertyValue(vProperties, &quot;CommandURL&quot;, pvValue)
+ Case UCase(&quot;TipText&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, V_STRING) Then GoTo Catch
+ ScriptForge.SF_Utils._SetPropertyValue(vProperties, &quot;Tooltip&quot;, pvValue)
+ Case UCase(&quot;Visible&quot;)
+ If Not ScriptForge.SF_Utils._Validate(pvValue, &quot;Value&quot;, ScriptForge.V_BOOLEAN) Then GoTo Catch
+ ScriptForge.SF_Utils._SetPropertyValue(vProperties, &quot;IsVisible&quot;, pvValue)
+ Case Else
+ bSet = False
+ End Select
+
+ oSettings.replaceByIndex(_Index, vProperties)
+ _Element.setSettings(oSettings)
+
+Finally:
+ _PropertySet = bSet
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ bSet = False
+ GoTo Finally
+End Function &apos; SFWidgets.SF_ToolbarButton._PropertySet
+
+REM -----------------------------------------------------------------------------
+Private Function _Repr() As String
+&apos;&apos;&apos; Convert the SF_ToolbarButton instance to a readable string, typically for debugging purposes (DebugPrint ...)
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Return:
+&apos;&apos;&apos; &quot;[Toolbar]: Name, Type (dialogname)
+ _Repr = &quot;[ToolbarButton]: &quot; &amp; Iif(Len(_Label) &gt; 0, _Label, _AccessibleName) &amp; &quot; - &quot; &amp; _CommandURL
+
+End Function &apos; SFWidgets.SF_ToolbarButton._Repr
+
+REM ============================================ END OF SFWIDGETS.SF_TOOLBARBUTTON
+</script:module> \ No newline at end of file
diff --git a/wizards/source/sfwidgets/__License.xba b/wizards/source/sfwidgets/__License.xba
new file mode 100644
index 0000000000..0d0990e37a
--- /dev/null
+++ b/wizards/source/sfwidgets/__License.xba
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
+<script:module xmlns:script="http://openoffice.org/2000/script" script:name="__License" script:language="StarBasic" script:moduleType="normal">
+&apos;&apos;&apos; Copyright 2019-2022 Jean-Pierre LEDURE, Rafael LIMA, Alain ROMEDENNE
+
+REM =======================================================================================================================
+REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
+REM === The SFWidgets library is one of the associated libraries. ===
+REM === Full documentation is available on https://help.libreoffice.org/ ===
+REM =======================================================================================================================
+
+&apos;&apos;&apos; ScriptForge is distributed in the hope that it will be useful,
+&apos;&apos;&apos; but WITHOUT ANY WARRANTY; without even the implied warranty of
+&apos;&apos;&apos; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+&apos;&apos;&apos; ScriptForge is free software; you can redistribute it and/or modify it under the terms of either (at your option):
+
+&apos;&apos;&apos; 1) The Mozilla Public License, v. 2.0. If a copy of the MPL was not
+&apos;&apos;&apos; distributed with this file, you can obtain one at http://mozilla.org/MPL/2.0/ .
+
+&apos;&apos;&apos; 2) The GNU Lesser General Public License as published by
+&apos;&apos;&apos; the Free Software Foundation, either version 3 of the License, or
+&apos;&apos;&apos; (at your option) any later version. If a copy of the LGPL was not
+&apos;&apos;&apos; distributed with this file, see http://www.gnu.org/licenses/ .
+
+</script:module> \ No newline at end of file
diff --git a/wizards/source/sfwidgets/dialog.xlb b/wizards/source/sfwidgets/dialog.xlb
new file mode 100644
index 0000000000..5d45468be1
--- /dev/null
+++ b/wizards/source/sfwidgets/dialog.xlb
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "library.dtd">
+<library:library xmlns:library="http://openoffice.org/2000/library" library:name="SFWidgets" library:readonly="false" library:passwordprotected="false"/> \ No newline at end of file
diff --git a/wizards/source/sfwidgets/script.xlb b/wizards/source/sfwidgets/script.xlb
new file mode 100644
index 0000000000..06975e6fc5
--- /dev/null
+++ b/wizards/source/sfwidgets/script.xlb
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "library.dtd">
+<library:library xmlns:library="http://openoffice.org/2000/library" library:name="SFWidgets" library:readonly="false" library:passwordprotected="false">
+ <library:element library:name="__License"/>
+ <library:element library:name="SF_Register"/>
+ <library:element library:name="SF_PopupMenu"/>
+ <library:element library:name="SF_Menu"/>
+ <library:element library:name="SF_MenuListener"/>
+ <library:element library:name="SF_Toolbar"/>
+ <library:element library:name="SF_ToolbarButton"/>
+</library:library> \ No newline at end of file