Files
odfstudio/wizards/source/sfwidgets/SF_Register.xba
T
Jean-Pierre Ledure 8a4ee0fb39 ScriptForge (SFWidgets) new ContextMenu service
Complete a predefined context menu with new items
placed at its bottom.

A context menu is obtained by a right-click
on several areas of a document. Each area has
its own context menu.
Each component model has its own set of context menus.

A context menu is usually predefined at
LibreOffice installation. Customization is done
statically with the Tools + Customize dialog.
The actual new service provides a mean
to make temporary additions at the bottom of a
context menu. Those changes are lost when
the document is closed.

The name of a context menu is the last component
of the resource URL:
   "private:resource/popupmenu/the-name-here"

Context menu items are either usual items or
line separators. Checkboxes or radio buttons
are not supported.
Items run a command or a script when clicked.

The service implements 2 methods:
   AddItem() adds an entry in the menu hierarchy
   Activate() shows or hides the added entries

A context menu can be defined from both Basic
and Python user scripts.

An update of the documentation is required.

Change-Id: Id77f1f2565d75e36c09b13972330d0f83b3f1db4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172355
Reviewed-by: Jean-Pierre Ledure <jp@ledure.be>
Tested-by: Jenkins
2024-08-24 18:29:12 +02:00

310 lines
14 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
<script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_Register" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
REM === The SFWidgets library is one of the associated libraries. ===
REM === Full documentation is available on https://help.libreoffice.org/ ===
REM =======================================================================================================================
Option Compatible
Option Explicit
&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
&apos;&apos;&apos; SF_Register
&apos;&apos;&apos; ===========
&apos;&apos;&apos; The ScriptForge framework includes
&apos;&apos;&apos; the master ScriptForge library
&apos;&apos;&apos; a number of &quot;associated&quot; libraries SF*
&apos;&apos;&apos; any user/contributor extension wanting to fit into the framework
&apos;&apos;&apos;
&apos;&apos;&apos; The main methods in this module allow the current library to cling to ScriptForge
&apos;&apos;&apos; - RegisterScriptServices
&apos;&apos;&apos; Register the list of services implemented by the current library
&apos;&apos;&apos; - _NewMenu
&apos;&apos;&apos; Create a new menu service instance.
&apos;&apos;&apos; Called from SFDocuments services with doc.CreateMenu(...)
&apos;&apos;&apos; - _NewContextMenu
&apos;&apos;&apos; Create a new context menu service instance.
&apos;&apos;&apos; Called from SFDocuments services with doc.ContextMenus(...)
&apos;&apos;&apos; - _NewPopupMenu
&apos;&apos;&apos; Create a new popup menu service instance.
&apos;&apos;&apos; Called from CreateScriptService(&quot;PopupMenu, ...)
&apos;&apos;&apos; - _NewToolbar
&apos;&apos;&apos; Create a new toolbar service instance.
&apos;&apos;&apos; Called from SFDocuments services with doc.Toolbars(...)
&apos;&apos;&apos; - _NewToolbarButton
&apos;&apos;&apos; Create a new toolbarbutton service instance.
&apos;&apos;&apos; Called from a Toolbar service with toolbar.ToolbarButtons(...)
&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
REM ================================================================== EXCEPTIONS
REM ================================================================= DEFINITIONS
REM ============================================================== PUBLIC METHODS
REM -----------------------------------------------------------------------------
Public Sub RegisterScriptServices() As Variant
&apos;&apos;&apos; Register into ScriptForge the list of the services implemented by the current library
&apos;&apos;&apos; Each library pertaining to the framework must implement its own version of this method
&apos;&apos;&apos;
&apos;&apos;&apos; It consists in successive calls to the RegisterService() and RegisterEventManager() methods
&apos;&apos;&apos; with 2 arguments:
&apos;&apos;&apos; ServiceName: the name of the service as a case-insensitive string
&apos;&apos;&apos; ServiceReference: the reference as an object
&apos;&apos;&apos; If the reference refers to a module, then return the module as an object:
&apos;&apos;&apos; GlobalScope.Library.Module
&apos;&apos;&apos; If the reference is a class instance, then return a string referring to the method
&apos;&apos;&apos; containing the New statement creating the instance
&apos;&apos;&apos; &quot;libraryname.modulename.function&quot;
With GlobalScope.ScriptForge.SF_Services
.RegisterService(&quot;Menu&quot;, &quot;SFWidgets.SF_Register._NewMenu&quot;) &apos; Reference to the function initializing the service
.RegisterService(&quot;ContextMenu&quot;, &quot;SFWidgets.SF_Register._NewContextMenu&quot;) &apos; id.
.RegisterService(&quot;PopupMenu&quot;, &quot;SFWidgets.SF_Register._NewPopupMenu&quot;) &apos; id.
.RegisterService(&quot;Toolbar&quot;, &quot;SFWidgets.SF_Register._NewToolbar&quot;) &apos; id.
.RegisterService(&quot;ToolbarButton&quot;, &quot;SFWidgets.SF_Register._NewToolbarButton&quot;) &apos; id.
End With
End Sub &apos; SFWidgets.SF_Register.RegisterScriptServices
REM =========================================================== PRIVATE FUNCTIONS
REM -----------------------------------------------------------------------------
Public Function _NewContextMenu(Optional ByVal pvArgs As Variant) As Object
&apos;&apos;&apos; Create a new instance of the SF_ContextMenu class
&apos;&apos;&apos; Args:
&apos;&apos;&apos; Component: the document&apos;s component requesting a context menu
&apos;&apos;&apos; ContextMenuName: a private:resource/popupmenu/... reference
&apos;&apos;&apos; SubmenuChar: Delimiter used in menu trees
&apos;&apos;&apos; Returns: the instance or Nothing
Dim oMenu As Object &apos; Return value
Dim Component As Object &apos; The document&apos;s component requesting a context menu
Dim ContextMenuName As String &apos; A &quot;private:resource/popupmenu/...&quot; reference
Dim SubmenuChar As String &apos; Delimiter in menu trees
If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
Set oMenu = Nothing
Check:
&apos; Get arguments, their check has been done upstream
If IsMissing(pvArgs) Or IsEmpty(pvArgs) Then pvArgs = Array()
If Not IsArray(pvArgs) Then pvArgs = Array(pvArgs)
If UBound(pvArgs) &gt;= 0 Then Set Component = pvArgs(0) Else Set Component = Nothing
If UBound(pvArgs) &gt;= 1 Then ContextMenuName = pvArgs(1) Else ContextMenuName = &quot;&quot;
If UBound(pvArgs) &gt;= 2 Then SubmenuChar = pvArgs(2) Else SubmenuChar = &quot;&gt;&quot;
Try:
If Not IsNull(Component) Then
Set oMenu = New SF_ContextMenu
With oMenu
Set .[Me] = oMenu
._Initialize(Component, ContextMenuName, SubmenuChar)
End With
Else
Set oMenu = Nothing
End If
Finally:
Set _NewContextMenu = oMenu
Exit Function
Catch:
GoTo Finally
End Function &apos; SFWidgets.SF_Register._NewContextMenu
REM -----------------------------------------------------------------------------
Public Function _NewMenu(Optional ByVal pvArgs As Variant) As Object
&apos;&apos;&apos; Create a new instance of the SF_Menu class
&apos;&apos;&apos; [called internally from SFDocuments.Document.CreateMenu() ONLY]
&apos;&apos;&apos; Args:
&apos;&apos;&apos; Component: the com.sun.star.lang.XComponent where to find the menubar to plug the new menu in
&apos;&apos;&apos; Header: the name/header of the menu
&apos;&apos;&apos; Before: the place where to put the new menu on the menubar (string or number &gt;= 1)
&apos;&apos;&apos; When not found =&gt; last position
&apos;&apos;&apos; SubmenuChar: the delimiter used in menu trees. Default = &quot;&gt;&quot;
&apos;&apos;&apos; Returns: the instance or Nothing
Dim oMenu As Object &apos; Return value
Dim oComponent As Object &apos; The document or formdocument&apos;s component - com.sun.star.lang.XComponent
Dim sHeader As String &apos; Menu header
Dim sBefore As String &apos; Position of menu as a string
Dim iBefore As Integer &apos; as a number
Dim sSubmenuChar As String &apos; Delimiter in menu trees
If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
Set oMenu = Nothing
Check:
&apos; Types and number of arguments are not checked because internal call only
Set oComponent = pvArgs(0)
sHeader = pvArgs(1)
Select Case VarType(pvArgs(2))
Case V_STRING : sBefore = pvArgs(2)
iBefore = 0
Case Else : sBefore = &quot;&quot;
iBefore = pvArgs(2)
End Select
sSubmenuChar = pvArgs(3)
Try:
If Not IsNull(oComponent) Then
Set oMenu = New SF_Menu
With oMenu
Set .[Me] = oMenu
._Initialize(oComponent, sHeader, sBefore, iBefore, sSubmenuChar)
End With
End If
Finally:
Set _NewMenu = oMenu
Exit Function
Catch:
GoTo Finally
End Function &apos; SFWidgets.SF_Register._NewMenu
REM -----------------------------------------------------------------------------
Public Function _NewPopupMenu(Optional ByVal pvArgs As Variant) As Object
&apos;&apos;&apos; Create a new instance of the SF_PopupMenu class
&apos;&apos;&apos; Args:
&apos;&apos;&apos; Event: a mouse event
&apos;&apos;&apos; If the event has no source or is not a mouse event, the menu is displayed above the actual window
&apos;&apos;&apos; X, Y: forced coordinates
&apos;&apos;&apos; SubmenuChar: Delimiter used in menu trees
&apos;&apos;&apos; Returns: the instance or Nothing
Dim oMenu As Object &apos; Return value
Dim Event As Variant &apos; Mouse event
Dim X As Long &apos; Mouse click coordinates
Dim Y As Long
Dim SubmenuChar As String &apos; Delimiter in menu trees
Dim vUno As Variant &apos; UNO type split into an array
Dim sEventType As String &apos; Event type, must be &quot;MouseEvent&quot;
Dim oControl As Object &apos; The dialog or form control view which triggered the event
Dim oWindow As Object &apos; ui.Window type
Dim oSession As Object : Set oSession = ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.Session&quot;)
Dim oUi As Object : Set oUi = ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.UI&quot;)
If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
Set oMenu = Nothing
Check:
&apos; Check and get arguments, their number may vary
If IsMissing(pvArgs) Or IsEmpty(pvArgs) Then pvArgs = Array()
If Not IsArray(pvArgs) Then pvArgs = Array(pvArgs)
If UBound(pvArgs) &gt;= 0 Then Event = pvArgs(0) Else Event = Nothing
If IsEmpty(Event) Then Event = Nothing
If UBound(pvArgs) &gt;= 1 Then X = pvArgs(1) Else X = 0
If UBound(pvArgs) &gt;= 2 Then Y = pvArgs(2) Else Y = 0
If UBound(pvArgs) &gt;= 3 Then SubmenuChar = pvArgs(3) Else SubmenuChar = &quot;&quot;
If Not ScriptForge.SF_Utils._Validate(Event, &quot;Event&quot;, ScriptForge.V_OBJECT) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(X, &quot;X&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(Y, &quot;Y&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(SubmenuChar, &quot;SubmenuChar&quot;, V_STRING) Then GoTo Finally
Try:
&apos; Find and identify the control that triggered the popup menu
Set oControl = Nothing
If Not IsNull(Event) Then
&apos; Determine the X, Y coordinates
vUno = Split(oSession.UnoObjectType(Event), &quot;.&quot;)
sEventType = vUno(UBound(vUno))
If UCase(sEventType) = &quot;MOUSEEVENT&quot; Then
X = Event.X
Y = Event.Y
&apos; Determine the window peer target
If oSession.HasUnoProperty(Event, &quot;Source&quot;) Then Set oControl = Event.Source.Peer
End If
End If
&apos; If not a mouse event, if no control, find what can be decent alternatives: (a menu header in) the actual window
If IsNull(oControl) Then
Set oWindow = oUi._IdentifyWindow(StarDesktop.getCurrentComponent()) &apos; A menu has been clicked necessarily in the current window
With oWindow
If Not IsNull(.Frame) Then Set oControl = .Frame.getContainerWindow()
End With
End If
If Not IsNull(oControl) Then
Set oMenu = New SF_PopupMenu
With oMenu
Set .[Me] = oMenu
._Initialize(oControl, X, Y, SubmenuChar)
End With
Else
Set oMenu = Nothing
End If
Finally:
Set _NewPopupMenu = oMenu
Exit Function
Catch:
GoTo Finally
End Function &apos; SFWidgets.SF_Register._NewPopupMenu
REM -----------------------------------------------------------------------------
Public Function _NewToolbar(Optional ByVal pvArgs As Variant) As Object
&apos;&apos;&apos; Create a new instance of the SF_Toolbar class
&apos;&apos;&apos; The &quot;Toolbar&quot; service must not be invoked directly in a user script
&apos;&apos;&apos; Args:
&apos;&apos;&apos; ToolbarDesc: a proto-toolbar object type. See ScriptForge.SF_UI for a detailed description
&apos;&apos;&apos; Returns:
&apos;&apos;&apos; the instance or Nothing
Dim oToolbar As Object &apos; Return value
Dim oToolbarDesc As Object &apos; A proto-toolbar description
If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
Set oToolbar = Nothing
Check:
Set oToolbarDesc = pvArgs(0)
Try:
Set oToolbar = New SF_Toolbar
With oToolbar
Set .[Me] = oToolbar
._Initialize(oToolbarDesc)
End With
Finally:
Set _NewToolbar = oToolbar
Exit Function
Catch:
GoTo Finally
End Function &apos; SFWidgets.SF_Register._NewToolbar
REM -----------------------------------------------------------------------------
Public Function _NewToolbarButton(Optional ByVal pvArgs As Variant) As Object
&apos;&apos;&apos; Create a new instance of the SF_ToolbarButton class
&apos;&apos;&apos; The &quot;ToolbarButton&quot; service must not be invoked directly in a user script
&apos;&apos;&apos; Args:
&apos;&apos;&apos; ToolbarButtonDesc: a proto-toolbarButton object type. See SFWidgets.SF_Toolbar for a detailed description
&apos;&apos;&apos; Returns:
&apos;&apos;&apos; the instance or Nothing
Dim oToolbarButton As Object &apos; Return value
Dim oToolbarButtonDesc As Object &apos; A proto-toolbarbutton description
If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
Set oToolbarButton = Nothing
Check:
Set oToolbarButtonDesc = pvArgs(0)
Try:
Set oToolbarButton = New SF_ToolbarButton
With oToolbarButton
Set .[Me] = oToolbarButton
._Initialize(oToolbarButtonDesc)
End With
Finally:
Set _NewToolbarButton = oToolbarButton
Exit Function
Catch:
GoTo Finally
End Function &apos; SFWidgets.SF_Register._NewToolbarButton
REM ============================================== END OF SFWIDGETS.SF_REGISTER
</script:module>