Intercepting a Context Menu

Introduction

The context menu is a popup menu that appears when you right-click on an object. This example demonstrates how to intercept the context menu and add or modify menu items.

Incepting a Context Menu is a somewhat involved process. OooDev provides a much simpler way to intercept the context menu and add or modify menu items.

By subscribing to the notify context menu execute of the document view via add_event_notify_context_menu_execute() method, you can intercept the context menu and add or modify menu items. No need to implement the XContextMenuInterception interface and register the interceptor. This is all done for you.

The add_event_notify_context_menu_execute() method takes a callback function that is called when the context menu is about to be displayed.

The callback event is a EventArgsGeneric object that contains the event data. The event data is a ContextMenuInterceptorEventData object that contains the event and the action trigger container.

By checking the CommandURL of the first item in the action trigger container, you can determine the context menu that is about to be displayed. You can then add or modify menu items as needed.

In the example below we are looking to modify the context menu when a user right-clicks on a sheet tab of a Calc document. We are looking for the .uno:Insert command URL at index 0. When found, a new menu item to the context menu.

Example Add Single Item

from __future__ import annotations
from typing import Any, TYPE_CHECKING
import uno
from ooo.dyn.ui.context_menu_interceptor_action import ContextMenuInterceptorAction as ContextMenuAction

from ooodev.adapter.ui.context_menu_interceptor import ContextMenuInterceptor
from ooodev.adapter.ui.context_menu_interceptor_event_data import ContextMenuInterceptorEventData
from ooodev.calc import CalcDoc
from ooodev.events.args.event_args_generic import EventArgsGeneric
from ooodev.gui.menu.popup.action.action_trigger_container import ActionTriggerContainer
from ooodev.gui.menu.popup.action.action_trigger_item import ActionTriggerItem
from ooodev.loader import Lo


if TYPE_CHECKING:
    from ooodev.calc.calc_sheet_view import CalcSheetView


def on_menu_intercept(
    src: ContextMenuInterceptor,
    event: EventArgsGeneric[ContextMenuInterceptorEventData],
    view: CalcSheetView,
) -> None:
    try:
        # selection = event.event_data.event.selection.get_selection()
        # print(selection)
        container = event.event_data.event.action_trigger_container
        print(container[0].CommandURL)
        if container[0].CommandURL == ".uno:Insert":
            container.insert_by_index(0, ActionTriggerItem(".uno:SelectTables", "Sheet..."))
            event.event_data.action = ContextMenuAction.EXECUTE_MODIFIED


def main():
    loader = Lo.load_office(connector=Lo.ConnectPipe())
    doc = CalcDoc.create_doc(loader=loader, visible=True)
    try:
        sheet = doc.sheets[0]
        sheet.set_active()
        sheet[0, 0].value = "Hello, World!"

        view = doc.get_view()
        view.add_event_notify_context_menu_execute(on_menu_intercept)
        # set a breakpoint here to see results.
        assert view

    finally:
        doc.close()
        Lo.close_office()


if __name__ == "__main__":
    main()

Inserts a Sheet... menu command at the beginning of the popup. The result is see in Fig. 1183.

Intercepting a Context Menu

Fig. 1183 Add Sheet… to the top of Context Menu

Example Add Multiple Items

Alternatively Add a container (submenu).

def on_menu_intercept(
    src: ContextMenuInterceptor,
    event: EventArgsGeneric[ContextMenuInterceptorEventData],
    view: CalcSheetView,
) -> None:
    try:
        container = event.event_data.event.action_trigger_container
        if container[0].CommandURL == ".uno:Insert":
            items = ActionTriggerContainer()
            items.insertByIndex(0, ActionTriggerItem(".uno:SelectTables", "Sheet..."))

            item = ActionTriggerItem("GoTo", "Go to", sub_menu=items)
            container.insert_by_index(7, item)
            event.event_data.action = ContextMenuAction.EXECUTE_MODIFIED

Inserts a Go To menu command with a submenu at index position of 7 of the popup. The result is see in Fig. 1184.

Intercepting a Context Menu

Fig. 1184 Add Go to in the Context Menu