wizards/Package_sfwidgets.mk                     |    2 
 wizards/source/scriptforge/SF_Services.xba       |    2 
 wizards/source/scriptforge/SF_Session.xba        |    9 
 wizards/source/scriptforge/python/scriptforge.py |   39 +
 wizards/source/sfdocuments/SF_Base.xba           |   18 
 wizards/source/sfdocuments/SF_Calc.xba           |   21 
 wizards/source/sfdocuments/SF_Document.xba       |  134 +++++
 wizards/source/sfdocuments/SF_Writer.xba         |   15 
 wizards/source/sfwidgets/SF_Menu.xba             |  590 +++++++++++++++++++++++
 wizards/source/sfwidgets/SF_MenuListener.xba     |  128 ++++
 wizards/source/sfwidgets/SF_PopupMenu.xba        |   82 ++-
 wizards/source/sfwidgets/SF_Register.xba         |   64 ++
 wizards/source/sfwidgets/script.xlb              |    2 
 13 files changed, 1071 insertions(+), 35 deletions(-)

New commits:
commit 88c82f10280a3de773091ddc41983c6d2f8ee157
Author:     Jean-Pierre Ledure <[email protected]>
AuthorDate: Fri Dec 3 12:18:17 2021 +0100
Commit:     Jean-Pierre Ledure <[email protected]>
CommitDate: Fri Dec 3 15:24:57 2021 +0100

    ScriptForge - (SFWidgets) new SF_Menu service
    
    Display a menu in the menubar of a document (form document to be done)
    After use, the menu will not be saved neither in the application settings,
    nor in the document. The menu setting does not affect the modified status 
of the
    document.
    
    The menu will be displayed, as usual, when its header in the menubar is 
clicked.
    When one of its items is selected, there are 3 alternative options:
      - a UNO command (like ".uno:About") is triggered
      - a user script is run receiving a standard argument defined in this 
service
      - one of above combined with a toggle of the status of the item
    
    The menu is described from top to bottom.
    Each menu item receives a numeric and a string identifier.
    Each menu item may be decorated with a tooltip and/or an icon.
    
    The AddItem(), AddCheckBox() and AddRadioButton() methods, when
    coompared with their equivalents in the SF_PopupMenu service,
    receive 2 additional arguments: Command and Script.
    
    The various document services receive 2 additional methods:
       CreateMenu(), returning a Menu service instance
       RemoveMenu()
    
    Very short example:
       menu = doc.CreateMenu("My menu", Before := "Help")
       menu.AddItem("First Item", Command := "About")
       menu.AddItem('2nd Item", Script := "... URI notation ...")
       menu.Dispose()   '   Once set the menu object may ve erased, listeners 
stay tuned
    Later in the lifecycle of the document, one may run:
       doc.RemoveMenu("My menu")   '  doc.RemoveMenu("File") works as well !!!
    
    All the functionalities are available both in Basic and Python user scripts.
    
    Change-Id: Iabd157573693e9648fcb06d36c90af9a22b17a6c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126309
    Tested-by: Jean-Pierre Ledure <[email protected]>
    Tested-by: Jenkins
    Reviewed-by: Jean-Pierre Ledure <[email protected]>

diff --git a/wizards/Package_sfwidgets.mk b/wizards/Package_sfwidgets.mk
index f89b83e58d5b..3e2041a5f810 100644
--- a/wizards/Package_sfwidgets.mk
+++ b/wizards/Package_sfwidgets.mk
@@ -20,6 +20,8 @@
 $(eval $(call 
gb_Package_Package,wizards_basicsrvsfwidgets,$(SRCDIR)/wizards/source/sfwidgets))
 
 $(eval $(call 
gb_Package_add_files,wizards_basicsrvsfwidgets,$(LIBO_SHARE_FOLDER)/basic/SFWidgets,\
+       SF_Menu.xba \
+       SF_MenuListener.xba \
        SF_PopupMenu.xba \
        SF_Register.xba \
        __License.xba \
diff --git a/wizards/source/scriptforge/SF_Services.xba 
b/wizards/source/scriptforge/SF_Services.xba
index 74bc110c9371..a2a96cb088c6 100644
--- a/wizards/source/scriptforge/SF_Services.xba
+++ b/wizards/source/scriptforge/SF_Services.xba
@@ -130,7 +130,7 @@ Try:
                                                                                
                                sLibrary = &quot;SFDocuments&quot;
                        Case &quot;dialog&quot;, &quot;dialogevent&quot;        
                :       sLibrary = &quot;SFDialogs&quot;
                        Case &quot;database&quot;                               
                        :       sLibrary = &quot;SFDatabases&quot;
-                       Case &quot;popupmenu&quot;                              
                :       sLibrary = &quot;SFWidgets&quot;
+                       Case &quot;menu&quot;, &quot;popupmenu&quot;            
                :       sLibrary = &quot;SFWidgets&quot;
                        Case Else
                End Select
        Else
diff --git a/wizards/source/scriptforge/SF_Session.xba 
b/wizards/source/scriptforge/SF_Session.xba
index db3cb9449889..f02a958768ce 100644
--- a/wizards/source/scriptforge/SF_Session.xba
+++ b/wizards/source/scriptforge/SF_Session.xba
@@ -994,12 +994,13 @@ REM 
=========================================================== PRIVATE FUNCTION
 
 REM 
-----------------------------------------------------------------------------
 Private Function _ExecuteScript(ByVal psScript As String _
-                                                                       , ByRef 
poEvent As Object _
+                                                                       , 
Optional ByRef pvArg As Variant _
                                                                        ) As 
Variant
 &apos;&apos;&apos;     Execute the script expressed in the scripting 
framework_URI notation
 &apos;&apos;&apos;     Args:
 &apos;&apos;&apos;             psScript: read 
https://wiki.openoffice.org/wiki/Documentation/DevGuide/Scripting/Scripting_Framework_URI_Specification
-&apos;&apos;&apos;             poEvent: the event object which triggered the 
execution. It is given as argument to the called script
+&apos;&apos;&apos;             pvArg: the unique argument to pass to the 
called script.
+&apos;&apos;&apos;                     It is often an event object that 
triggered the execution of the script.
 &apos;&apos;&apos;     Returns:
 &apos;&apos;&apos;             The return value after the script execution. 
May be ignored for events
 
@@ -1020,9 +1021,9 @@ Try:
                sScript = vStrings(0)   :       sLanguage = vStrings(1) :       
sScope = vStrings(2)
                &apos;  Execute script
                If UCase(sLanguage) = &quot;BASIC&quot; Then
-                       _ExecuteScript = ExecuteBasicScript(sScope, sScript, 
poEvent)
+                       _ExecuteScript = ExecuteBasicScript(sScope, sScript, 
pvArg)
                Else    &apos;  Python
-                       _ExecuteScript = ExecutePythonScript(sScope, sScript, 
poEvent)
+                       _ExecuteScript = ExecutePythonScript(sScope, sScript, 
pvArg)
                End If
        End If
 
diff --git a/wizards/source/scriptforge/python/scriptforge.py 
b/wizards/source/scriptforge/python/scriptforge.py
index 9dc95d21f715..18334f3684c8 100644
--- a/wizards/source/scriptforge/python/scriptforge.py
+++ b/wizards/source/scriptforge/python/scriptforge.py
@@ -1774,12 +1774,18 @@ class SFDocuments:
         def CloseDocument(self, saveask = True):
             return self.ExecMethod(self.vbMethod, 'CloseDocument', saveask)
 
+        def CreateMenu(self, menuheader, before = '', submenuchar = '>'):
+            return self.ExecMethod(self.vbMethod, 'CreateMenu', menuheader, 
before, submenuchar)
+
         def ExportAsPDF(self, filename, overwrite = False, pages = '', 
password = '', watermark = ''):
             return self.ExecMethod(self.vbMethod, 'ExportAsPDF', filename, 
overwrite, pages, password, watermark)
 
         def PrintOut(self, pages = '', copies = 1):
             return self.ExecMethod(self.vbMethod, 'PrintOut', pages, copies)
 
+        def RemoveMenu(self, menuheader):
+            return self.ExecMethod(self.vbMethod, 'RemoveMenu', menuheader)
+
         def RunCommand(self, command):
             return self.ExecMethod(self.vbMethod, 'RunCommand', command)
 
@@ -2229,6 +2235,39 @@ class SFWidgets:
         """
     pass
 
+    # #########################################################################
+    # SF_Menu CLASS
+    # #########################################################################
+    class SF_Menu(SFServices):
+        """
+            Display a menu in the menubar of a document or a form document.
+            After use, the menu will not be saved neither in the application 
settings, nor in the document.
+            The menu will be displayed, as usual, when its header in the 
menubar is clicked.
+            When one of its items is selected, there are 3 alternative options:
+            - a UNO command (like ".uno:About") is triggered
+            - a user script is run receiving a standard argument defined in 
this service
+            - one of above combined with a toggle of the status of the item
+            The menu is described from top to bottom. Each menu item receives 
a numeric and a string identifier.
+            """
+        # Mandatory class properties for service registration
+        serviceimplementation = 'basic'
+        servicename = 'SFWidgets.Menu'
+        servicesynonyms = ('menu', 'sfwidgets.menu')
+        serviceproperties = dict(ShortcutCharacter = False, SubmenuCharacter = 
False)
+
+        def AddCheckBox(self, menuitem, name = '', status = False, icon = '', 
tooltip = '',
+                        command = '', script = ''):
+            return self.ExecMethod(self.vbMethod, 'AddCheckBox', menuitem, 
name, status, icon, tooltip,
+                                   command, script)
+
+        def AddItem(self, menuitem, name = '', icon = '', tooltip = '', 
command = '', script = ''):
+            return self.ExecMethod(self.vbMethod, 'AddItem', menuitem, name, 
icon, tooltip, command, script)
+
+        def AddRadioButton(self, menuitem, name = '', status = False, icon = 
'', tooltip = '',
+                           command = '', script = ''):
+            return self.ExecMethod(self.vbMethod, 'AddRadioButton', menuitem, 
name, status, icon, tooltip,
+                                   command, script)
+
     # #########################################################################
     # SF_PopupMenu CLASS
     # #########################################################################
diff --git a/wizards/source/sfdocuments/SF_Base.xba 
b/wizards/source/sfdocuments/SF_Base.xba
index efdc57be9b4d..0199341bb5da 100644
--- a/wizards/source/sfdocuments/SF_Base.xba
+++ b/wizards/source/sfdocuments/SF_Base.xba
@@ -120,7 +120,7 @@ Check:
        If IsMissing(SaveAsk) Or IsEmpty(SaveAsk) Then SaveAsk = True
        If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
                If Not _IsStillAlive(True) Then GoTo Finally
-               If Not ScriptForge.SF_Utils._Validate(SaveAsk, 
&quot;SaveAsk&quot;, V_BOOLEAN) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(SaveAsk, 
&quot;SaveAsk&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
        End If
 
 Try:
@@ -442,12 +442,15 @@ Public Function Methods() As Variant
        Methods = Array( _
                                        &quot;Activate&quot; _
                                        , &quot;CloseDocument&quot; _
+                                       , &quot;CloseFormDocument&quot; _
+                                       , &quot;CreateMenu&quot; _
                                        , &quot;FormDocuments&quot; _
                                        , &quot;Forms&quot; _
                                        , &quot;GetDatabase&quot; _
                                        , &quot;IsLoaded&quot; _
                                        , &quot;OpenFormDocument&quot; _
                                        , &quot;PrintOut&quot; _
+                                       , &quot;RemoveMenu&quot; _
                                        , &quot;RunCommand&quot; _
                                        , &quot;Save&quot; _
                                        , &quot;SaveAs&quot; _
@@ -791,6 +794,19 @@ Public Function Activate() As Boolean
        Activate = [_Super].Activate()
 End Function    &apos;   SFDocuments.SF_Base.Activate
 
+REM 
-----------------------------------------------------------------------------
+Public Function CreateMenu(Optional ByVal MenuHeader As Variant _
+                                                               , Optional 
ByVal Before As Variant _
+                                                               , Optional 
ByVal SubmenuChar As Variant _
+                                                               ) As Object
+       Set CreateMenu = [_Super].CreateMenu(MenuHeader, Before, SubmenuChar)
+End Function   &apos;  SFDocuments.SF_Base.CreateMenu
+
+REM 
-----------------------------------------------------------------------------
+Public Function RemoveMenu(Optional ByVal MenuHeader As Variant) As Boolean
+       RemoveMenu = [_Super].RemoveMenu(MenuHeader)
+End Function   &apos;  SFDocuments.SF_Base.RemoveMenu
+
 REM 
-----------------------------------------------------------------------------
 Public Sub RunCommand(Optional ByVal Command As Variant)
        [_Super].RunCommand(Command)
diff --git a/wizards/source/sfdocuments/SF_Calc.xba 
b/wizards/source/sfdocuments/SF_Calc.xba
index e5b35e4afa12..f22a64642e36 100644
--- a/wizards/source/sfdocuments/SF_Calc.xba
+++ b/wizards/source/sfdocuments/SF_Calc.xba
@@ -1647,6 +1647,7 @@ Public Function Methods() As Variant
                                        , &quot;CopyToCell&quot; _
                                        , &quot;CopyToRange&quot; _
                                        , &quot;CreateChart&quot; _
+                                       , &quot;CreateMenu&quot; _
                                        , &quot;DAvg&quot; _
                                        , &quot;DCount&quot; _
                                        , &quot;DMax&quot; _
@@ -1665,6 +1666,7 @@ Public Function Methods() As Variant
                                        , &quot;OpenRangeSelector&quot; _
                                        , &quot;Printf&quot; _
                                        , &quot;PrintOut&quot; _
+                                       , &quot;RemoveMenu&quot; _
                                        , &quot;RemoveSheet&quot; _
                                        , &quot;RenameSheet&quot; _
                                        , &quot;RunCommand&quot; _
@@ -2889,9 +2891,9 @@ Check:
                If Not ScriptForge.SF_Utils._ValidateArray(SortKeys, 
&quot;SortKeys&quot;, 1, V_NUMERIC, True) Then GoTo Finally
                If Not ScriptForge.SF_Utils._Validate(DestinationCell, 
&quot;DestinationCell&quot;, V_STRING) Then GoTo Finally
                If Not ScriptForge.SF_Utils._ValidateArray(SortOrder, 
&quot;SortOrder&quot;, 1, V_STRING, True) Then GoTo Finally
-               If Not ScriptForge.SF_Utils._Validate(ContainsHeader, 
&quot;ContainsHeader&quot;, V_BOOLEAN) Then GoTo Finally
-               If Not ScriptForge.SF_Utils._Validate(CaseSensitive, 
&quot;CaseSensitive&quot;, V_BOOLEAN) Then GoTo Finally
-               If Not ScriptForge.SF_Utils._Validate(SortColumns, 
&quot;SortColumns&quot;, V_BOOLEAN) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(ContainsHeader, 
&quot;ContainsHeader&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(CaseSensitive, 
&quot;CaseSensitive&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(SortColumns, 
&quot;SortColumns&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
        End If
        Set oRangeAddress = _ParseAddress(Range)
        If Len(DestinationCell) &gt; 0 Then Set oDestRange = 
_ParseAddress(DestinationCell)
@@ -3067,6 +3069,14 @@ Public Function CloseDocument(Optional ByVal SaveAsk As 
Variant) As Boolean
        CloseDocument = [_Super].CloseDocument(SaveAsk)
 End Function   &apos;   SFDocuments.SF_Calc.CloseDocument
 
+REM 
-----------------------------------------------------------------------------
+Public Function CreateMenu(Optional ByVal MenuHeader As Variant _
+                                                               , Optional 
ByVal Before As Variant _
+                                                               , Optional 
ByVal SubmenuChar As Variant _
+                                                               ) As Object
+       Set CreateMenu = [_Super].CreateMenu(MenuHeader, Before, SubmenuChar)
+End Function   &apos;  SFDocuments.SF_Calc.CreateMenu
+
 REM 
-----------------------------------------------------------------------------
 Public Function ExportAsPDF(Optional ByVal FileName As Variant _
                                                        , Optional ByVal 
Overwrite As Variant _
@@ -3077,6 +3087,11 @@ Public Function ExportAsPDF(Optional ByVal FileName As 
Variant _
        ExportAsPDF = [_Super].ExportAsPDF(FileName, Overwrite, Pages, 
Password, Watermark)
 End Function   &apos;   SFDocuments.SF_Calc.ExportAsPDF
 
+REM 
-----------------------------------------------------------------------------
+Public Function RemoveMenu(Optional ByVal MenuHeader As Variant) As Boolean
+       RemoveMenu = [_Super].RemoveMenu(MenuHeader)
+End Function   &apos;  SFDocuments.SF_Calc.RemoveMenu
+
 REM 
-----------------------------------------------------------------------------
 Public Sub RunCommand(Optional ByVal Command As Variant)
        [_Super].RunCommand(Command)
diff --git a/wizards/source/sfdocuments/SF_Document.xba 
b/wizards/source/sfdocuments/SF_Document.xba
index 00aa22fc08b4..37c4e4e6bbe7 100644
--- a/wizards/source/sfdocuments/SF_Document.xba
+++ b/wizards/source/sfdocuments/SF_Document.xba
@@ -436,7 +436,7 @@ Check:
        If IsMissing(SaveAsk) Or IsEmpty(SaveAsk) Then SaveAsk = True
        If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
                If Not _IsStillAlive() Then GoTo Finally
-               If Not ScriptForge.SF_Utils._Validate(SaveAsk, 
&quot;SaveAsk&quot;, V_BOOLEAN) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(SaveAsk, 
&quot;SaveAsk&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
        End If
 
 Try:
@@ -459,6 +459,63 @@ Catch:
        GoTo Finally
 End Function   &apos;   SFDocuments.SF_Document.CloseDocument
 
+REM 
-----------------------------------------------------------------------------
+Public Function CreateMenu(Optional ByVal MenuHeader As Variant _
+                                                               , Optional 
ByVal Before As Variant _
+                                                               , Optional 
ByVal SubmenuChar As Variant _
+                                                               , Optional 
ByRef _Document As Variant _
+                                                               ) As Object
+&apos;&apos;&apos; Create a new menu entry in the document&apos;s menubar
+&apos;&apos;&apos;     The menu is not intended to be saved neither in the 
LibreOffice global environment, nor in the document
+&apos;&apos;&apos;     The method returns a SFWidgets.Menu instance. Its 
methods let define the menu further.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             MenuHeader: 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;             _Document: undocumented argument to designate 
the document where the menu will be located
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             A SFWidgets.Menu instance or Nothing
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             Dim oMenu As Object
+&apos;&apos;&apos;             Set oMenu = oDoc.CreateMenu(&quot;My 
menu&quot;, Before := &quot;Styles&quot;)
+&apos;&apos;&apos;             With oMenu
+&apos;&apos;&apos;                     .AddItem(&quot;Item 1&quot;, Command := 
&quot;About&quot;)
+&apos;&apos;&apos;                     &apos;...
+&apos;&apos;&apos;                     .Dispose()      &apos;  When definition 
is complete, the menu instance may be disposed
+&apos;&apos;&apos;             End With
+&apos;&apos;&apos;                     &apos; ...
+
+Dim oMenu As Object                    &apos;  return value
+Const cstThisSub = &quot;SFDocuments.Document.CreateMenu&quot;
+Const cstSubArgs = &quot;MenuHeader, [Before=&quot;&quot;&quot;&quot;], 
[SubmenuChar=&quot;&quot;&gt;&quot;&quot;]&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       Set oMenu = Nothing
+
+Check:
+       If IsMissing(Before) Or IsEmpty(Before) Then Before = &quot;&quot;
+       If IsMissing(SubmenuChar) Or IsEmpty(SubmenuChar) Then SubmenuChar = 
&quot;&quot;
+       If IsMissing(_Document) Or IsEmpty(_Document) Or IsNull(_Document) Then 
Set _Document = _Component
+
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not _IsStillAlive() Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(MenuHeader, 
&quot;MenuHeader&quot;, V_STRING) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(Before, 
&quot;Before&quot;, V_STRING) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(SubmenuChar, 
&quot;SubmenuChar&quot;, V_STRING) Then GoTo Finally
+       End If
+
+Try:
+       Set oMenu = 
ScriptForge.SF_Services.CreateScriptService(&quot;SFWidgets.Menu&quot;, 
_Document, MenuHeader, Before, SubmenuChar)
+
+Finally:
+       Set CreateMenu = oMenu
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;   SFDocuments.SF_Document.CreateMenu
+
 REM 
-----------------------------------------------------------------------------
 Public Function ExportAsPDF(Optional ByVal FileName As Variant _
                                                        , Optional ByVal 
Overwrite As Variant _
@@ -502,7 +559,7 @@ Check:
        If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
                If Not _IsStillAlive() Then GoTo Finally
                If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) 
Then GoTo Finally
-               If Not SF_Utils._Validate(Overwrite, &quot;Overwrite&quot;, 
V_BOOLEAN) Then GoTo Finally
+               If Not SF_Utils._Validate(Overwrite, &quot;Overwrite&quot;, 
ScriptForge.V_BOOLEAN) Then GoTo Finally
                If Not SF_Utils._Validate(Pages, &quot;Pages&quot;, V_STRING) 
Then GoTo Finally
                If Not SF_Utils._Validate(Password, &quot;Password&quot;, 
V_STRING) Then GoTo Finally
                If Not SF_Utils._Validate(Watermark, &quot;Watermark&quot;, 
V_STRING) Then GoTo Finally
@@ -596,8 +653,10 @@ Public Function Methods() As Variant
        Methods = Array( _
                                        &quot;Activate&quot; _
                                        , &quot;CloseDocument&quot; _
+                                       , &quot;CreateMenu&quot; _
                                        , &quot;ExportAsPDF&quot; _
                                        , &quot;PrintOut&quot; _
+                                       , &quot;RemoveMenu&quot; _
                                        , &quot;RunCommand&quot; _
                                        , &quot;Save&quot; _
                                        , &quot;SaveAs&quot; _
@@ -686,6 +745,73 @@ Public Function Properties() As Variant
 
 End Function   &apos;  SFDocuments.SF_Document.Properties
 
+REM 
-----------------------------------------------------------------------------
+Public Function RemoveMenu(Optional ByVal MenuHeader As Variant _
+                                                       , Optional ByRef 
_Document As Variant _
+) As Boolean
+&apos;&apos;&apos; Remove a menu entry in the document&apos;s menubar
+&apos;&apos;&apos;     The removal is not intended to be saved neither in the 
LibreOffice global environment, nor in the document
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             MenuHeader: the name/header of the menu, 
without tilde &quot;~&quot;, as a case-sensitive string
+&apos;&apos;&apos;             _Document: undocumented argument to designate 
the document where the menu is located
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True when successful
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             oDoc.RemoveMenu(&quot;File&quot;)
+&apos;&apos;&apos;                     &apos; ...
+
+Dim bRemove As Boolean                 &apos;  Return value
+Dim oLayout As Object                  &apos;  
com.sun.star.comp.framework.LayoutManager
+Dim oMenuBar As Object                 &apos;  com.sun.star.awt.XMenuBar or 
stardiv.Toolkit.VCLXMenuBar
+Dim sName As String                            &apos;  Menu name
+Dim iMenuId As Integer                 &apos;  Menu identifier
+Dim iMenuPosition As Integer   &apos;  Menu position &gt;= 0
+Dim i As Integer
+Const cstTilde = &quot;~&quot;
+
+Const cstThisSub = &quot;SFDocuments.Document.RemoveMenu&quot;
+Const cstSubArgs = &quot;MenuHeader&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       bRemove = False
+
+Check:
+       If IsMissing(_Document) Or IsEmpty(_Document) Or IsNull(_Document) Then 
Set _Document = _Component
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not _IsStillAlive() Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(MenuHeader, 
&quot;MenuHeader&quot;, V_STRING) Then GoTo Finally
+       End If
+
+Try:
+       Set oLayout = _Document.CurrentController.Frame.LayoutManager
+       Set oMenuBar = 
oLayout.getElement(&quot;private:resource/menubar/menubar&quot;).XMenuBar
+
+       &apos;  Search the menu identifier to remove by its name, Mark its 
position
+       With oMenuBar
+               iMenuPosition = -1
+               For i = 0 To .ItemCount - 1
+                       iMenuId = .getItemId(i)
+                       sName = Replace(.getItemText(iMenuId), cstTilde, 
&quot;&quot;)
+                       If MenuHeader= sName Then
+                               iMenuPosition = i
+                               Exit For
+                       End If
+               Next i
+               &apos;  Remove the found menu item
+               If iMenuPosition &gt;= 0 Then
+                       .removeItem(iMenuPosition, 1)
+                       bRemove = True
+               End If
+       End With
+
+Finally:
+       RemoveMenu = bRemove
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;   SFDocuments.SF_Document.RemoveMenu
+
 REM 
-----------------------------------------------------------------------------
 Public Sub RunCommand(Optional ByVal Command As Variant)
 &apos;&apos;&apos; Run on the document the given menu command. The command is 
executed without arguments
@@ -811,7 +937,7 @@ Check:
        If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
                If Not _IsStillAlive() Then GoTo Finally
                If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) 
Then GoTo Finally
-               If Not SF_Utils._Validate(Overwrite, &quot;Overwrite&quot;, 
V_BOOLEAN) Then GoTo Finally
+               If Not SF_Utils._Validate(Overwrite, &quot;Overwrite&quot;, 
ScriptForge.V_BOOLEAN) Then GoTo Finally
                If Not SF_Utils._Validate(Password, &quot;Password&quot;, 
V_STRING) Then GoTo Finally
                If Not SF_Utils._Validate(FilterName, &quot;FilterName&quot;, 
V_STRING) Then GoTo Finally
                If Not SF_Utils._Validate(FilterOptions, 
&quot;FilterOptions&quot;, V_STRING) Then GoTo Finally
@@ -910,7 +1036,7 @@ Check:
        If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
                If Not _IsStillAlive() Then GoTo Finally
                If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) 
Then GoTo Finally
-               If Not SF_Utils._Validate(Overwrite, &quot;Overwrite&quot;, 
V_BOOLEAN) Then GoTo Finally
+               If Not SF_Utils._Validate(Overwrite, &quot;Overwrite&quot;, 
ScriptForge.V_BOOLEAN) Then GoTo Finally
                If Not SF_Utils._Validate(Password, &quot;Password&quot;, 
V_STRING) Then GoTo Finally
                If Not SF_Utils._Validate(FilterName, &quot;FilterName&quot;, 
V_STRING) Then GoTo Finally
                If Not SF_Utils._Validate(FilterOptions, 
&quot;FilterOptions&quot;, V_STRING) Then GoTo Finally
diff --git a/wizards/source/sfdocuments/SF_Writer.xba 
b/wizards/source/sfdocuments/SF_Writer.xba
index 4acdd5c750f0..96ed289f92ff 100644
--- a/wizards/source/sfdocuments/SF_Writer.xba
+++ b/wizards/source/sfdocuments/SF_Writer.xba
@@ -219,9 +219,11 @@ Public Function Methods() As Variant
        Methods = Array( _
                                        &quot;Activate&quot; _
                                        , &quot;CloseDocument&quot; _
+                                       , &quot;CreateMenu&quot; _
                                        , &quot;ExportAsPDF&quot; _
                                        , &quot;Forms&quot; _
                                        , &quot;PrintOut&quot; _
+                                       , &quot;RemoveMenu&quot; _
                                        , &quot;RunCommand&quot; _
                                        , &quot;Save&quot; _
                                        , &quot;SaveAs&quot; _
@@ -492,6 +494,14 @@ Public Function CloseDocument(Optional ByVal SaveAsk As 
Variant) As Boolean
        CloseDocument = [_Super].CloseDocument(SaveAsk)
 End Function   &apos;   SFDocuments.SF_Writer.CloseDocument
 
+REM 
-----------------------------------------------------------------------------
+Public Function CreateMenu(Optional ByVal MenuHeader As Variant _
+                                                               , Optional 
ByVal Before As Variant _
+                                                               , Optional 
ByVal SubmenuChar As Variant _
+                                                               ) As Object
+       Set CreateMenu = [_Super].CreateMenu(MenuHeader, Before, SubmenuChar)
+End Function   &apos;  SFDocuments.SF_Writer.CreateMenu
+
 REM 
-----------------------------------------------------------------------------
 Public Function ExportAsPDF(Optional ByVal FileName As Variant _
                                                        , Optional ByVal 
Overwrite As Variant _
@@ -502,6 +512,11 @@ Public Function ExportAsPDF(Optional ByVal FileName As 
Variant _
        ExportAsPDF = [_Super].ExportAsPDF(FileName, Overwrite, Pages, 
Password, Watermark)
 End Function   &apos;   SFDocuments.SF_Writer.ExportAsPDF
 
+REM 
-----------------------------------------------------------------------------
+Public Function RemoveMenu(Optional ByVal MenuHeader As Variant) As Boolean
+       RemoveMenu = [_Super].RemoveMenu(MenuHeader)
+End Function   &apos;  SFDocuments.SF_Writer.RemoveMenu
+
 REM 
-----------------------------------------------------------------------------
 Public Sub RunCommand(Optional ByVal Command As Variant)
        [_Super].RunCommand(Command)
diff --git a/wizards/source/sfwidgets/SF_Menu.xba 
b/wizards/source/sfwidgets/SF_Menu.xba
new file mode 100644
index 000000000000..308e959d1cee
--- /dev/null
+++ b/wizards/source/sfwidgets/SF_Menu.xba
@@ -0,0 +1,590 @@
+<?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 ObjectoDoc 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.openoffice.org/wiki/Documentation/DevGuide/Scripting/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;, otherwide &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.openoffice.org/wiki/Documentation/DevGuide/Scripting/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.openoffice.org/wiki/Documentation/DevGuide/Scripting/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;, otherwide &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 i As Integer
+Const cstTilde = &quot;~&quot;
+
+Try:
+       &apos;  Initialize the menubar
+       Set oLayout = poComponent.CurrentController.Frame.LayoutManager
+       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 000000000000..0b1f2b6fd0e5
--- /dev/null
+++ b/wizards/source/sfwidgets/SF_MenuListener.xba
@@ -0,0 +1,128 @@
+<?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 oSession As Object                         &apos;  SF_Session service
+Dim vScript As Variant                         &apos;  Split command in 
script/argument
+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 
radiobttons and checkboxes
+               sCommand = .getCommand(iMenuId)
+               bStatus = .isItemChecked(iMenuId)
+       End With
+       
+       If Len(sCommand) &gt; 0 Then
+               If Left(sCommand, Len(cstUnoPrefix)) = cstUnoPrefix Then
+                       &apos;  Execute uno command
+                       Set oFrame = 
StarDesktop.CurrentComponent.CurrentController.Frame       &apos;  A menu has 
been clicked necessarily in the current window
+                       Set oDispatcher = 
ScriptForge.SF_Utils._GetUNOService(&quot;DispatchHelper&quot;)
+                       oDispatcher.executeDispatch(oFrame, sCommand, 
&quot;&quot;, 0, oArgs())
+               Else
+                       &apos;  Execute script
+                       Set oSession = 
ScriptForge.SF_Services.CreateScriptService(&quot;Session&quot;)
+                       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 
SFDIALOGS.SF_DIALOGLISTENER
+</script:module>
\ No newline at end of file
diff --git a/wizards/source/sfwidgets/SF_PopupMenu.xba 
b/wizards/source/sfwidgets/SF_PopupMenu.xba
index 8f231983551a..3d5ba65a80f8 100644
--- a/wizards/source/sfwidgets/SF_PopupMenu.xba
+++ b/wizards/source/sfwidgets/SF_PopupMenu.xba
@@ -22,7 +22,7 @@ Option Explicit
 &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;             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
@@ -34,7 +34,7 @@ Option Explicit
 &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 invocating the 
PopupMenu service
+&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;
@@ -45,14 +45,38 @@ Option Explicit
 &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;             Example 1: simulate an extract of the View menu 
in the menubar of the Basic IDE
+&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;                                     
.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;
@@ -74,7 +98,7 @@ Option Explicit
 &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
@@ -98,6 +122,7 @@ Private MenuRoot                     As Object               
&apos; stardiv.vcl.PopupMenu or com.sun.star.awt.X
 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
 
@@ -105,6 +130,7 @@ 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;
@@ -122,6 +148,8 @@ Private Sub Class_Initialize()
        Set MenuRoot = Nothing
        LastItem = 0
        Set Rectangle = Nothing
+       Set PeerWindow = Nothing
+       MenubarMenu = False
 End Sub                &apos;  SFWidgets.SF_PopupMenu Constructor
 
 REM 
-----------------------------------------------------------------------------
@@ -187,7 +215,7 @@ Public Function AddCheckBox(Optional ByVal MenuItem As 
Variant _
 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;
+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
@@ -228,7 +256,7 @@ Public Function AddItem(Optional ByVal MenuItem As Variant _
 &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;                     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
@@ -247,7 +275,7 @@ Public Function AddItem(Optional ByVal MenuItem As Variant _
 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;
+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
@@ -307,7 +335,7 @@ Public Function AddRadioButton(Optional ByVal MenuItem As 
Variant _
 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;
+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
@@ -360,7 +388,7 @@ Public Function Execute(Optional ByVal ReturnId As Variant) 
As Variant
 Dim vMenuItem As Variant                               &apos;  Return value
 
 Const cstThisSub = &quot;SFWidgets.PopupMenu.Execute&quot;
-Const cstSubArgs = &quot;[ReturnId = True]&quot;
+Const cstSubArgs = &quot;[ReturnId=True]&quot;
 
        If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
        vMenuItem = 0
@@ -374,7 +402,7 @@ Check:
 
 Try:
        vMenuItem = MenuRoot.Execute(PeerWindow, Rectangle, 
com.sun.star.awt.PopupMenuDirection.EXECUTE_DEFAULT)
-       If Not ReturnId Then vMenuItem = MenuIdentification.Item(Str(vMenuItem))
+       If Not ReturnId Then vMenuItem = 
MenuIdentification.Item(CStr(vMenuItem))
 
 Finally:
        Execute = vMenuItem
@@ -483,6 +511,7 @@ Public Function _AddItem(ByVal MenuItem 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:
@@ -501,6 +530,9 @@ Public Function _AddItem(ByVal MenuItem As String _
 &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
 
@@ -510,9 +542,12 @@ 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
@@ -534,16 +569,16 @@ Try:
                                Case cstNormal
                                        .insertItem(LastItem, sName, 0, -1)
                                Case cstCheck
-                                       .insertItem(LastItem, sName, 
com.sun.star.awt.MenuItemStyle.CHECKABLE, -1)
+                                       .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, -1)
+                                       .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(Str(LastItem), Name)
+                       MenuIdentification.Add(CStr(LastItem), Name)
 
                        &apos;  Add the icon when relevant
                        If Len(Icon) &gt; 0 Then
@@ -553,6 +588,16 @@ Try:
 
                        &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
 
@@ -566,7 +611,7 @@ Catch:
 End Function   &apos;  SFWidgets.SF_PopupMenu._AddItem
 
 REM 
-----------------------------------------------------------------------------
-Private Function _GetImageFromURL(psUrl as String) As Object
+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
@@ -593,7 +638,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SFWidgets.SF°PopupMenu._GetImageFromUrl
+End Function   &apos;  SFWidgets.SF_PopupMenu._GetImageFromUrl
 
 REM 
-----------------------------------------------------------------------------
 Private Function _GetPopupMenu(ByVal psSubmenu As String) As Object
@@ -635,6 +680,7 @@ Try:
                                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
@@ -722,7 +768,7 @@ End Function        &apos;  
SFWidgets.SF_PopupMenu._PropertyGet
 
 REM 
-----------------------------------------------------------------------------
 Private Function _Repr() As String
-&apos;&apos;&apos;     Convert the Model instance to a readable string, 
typically for debugging purposes (DebugPrint ...)
+&apos;&apos;&apos;     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)
diff --git a/wizards/source/sfwidgets/SF_Register.xba 
b/wizards/source/sfwidgets/SF_Register.xba
index 4dbb84f03104..2c58b858d1e9 100644
--- a/wizards/source/sfwidgets/SF_Register.xba
+++ b/wizards/source/sfwidgets/SF_Register.xba
@@ -20,8 +20,12 @@ Option Explicit
 &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;                             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
@@ -46,21 +50,72 @@ Public Sub RegisterScriptServices() As Variant
 &apos;&apos;&apos;                             
&quot;libraryname.modulename.function&quot;
 
        With GlobalScope.ScriptForge.SF_Services
-               .RegisterService(&quot;PopupMenu&quot;,                 
&quot;SFWidgets.SF_Register._NewPopupMenu&quot;)                &apos;  
Reference to the function initializing the service
+               .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.
        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; Args:
+&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 ThisComponent
 &apos;&apos;&apos;             X, Y: forced coordinates
-&apos;&apos;&apos;             SubmenuChar: Delimiter in menu trees
+&apos;&apos;&apos;             SubmenuChar: Delimiter used in menu trees
 &apos;&apos;&apos;     Returns: the instance or Nothing
 
 Dim oMenu As Object                                    &apos;  Return value
@@ -86,6 +141,7 @@ Check:
        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
        Set oMenu = Nothing
 
 Try:
diff --git a/wizards/source/sfwidgets/script.xlb 
b/wizards/source/sfwidgets/script.xlb
index a32c363d4ac6..40e9f4c23df2 100644
--- a/wizards/source/sfwidgets/script.xlb
+++ b/wizards/source/sfwidgets/script.xlb
@@ -4,4 +4,6 @@
  <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:library>
\ No newline at end of file

Reply via email to