Popup from Dictionary or JSON
Demonstrates creating a popup menu using a dictionary. This example mimics the popup menu displayed Calc Cell.
This example is the same data that is use to export Sample Popup Menu JSON Normal Data and Sample Popup Menu JSON Dynamic Data.
The module
key is used to instruct PopupCreator
to lookup up the command info from CmdInfo
The ModuleNamesKind
is used to specify the module to lookup the command info from.
Example
Example code
from __future__ import annotations
from typing import Any, cast, TYPE_CHECKING
import uno
from com.sun.star.awt import Rectangle
from ooo.dyn.awt.menu_item_style import MenuItemStyleEnum
from ooodev.calc import CalcDoc
from ooodev.loader import Lo
from ooodev.events.args.event_args import EventArgs
from ooodev.gui.menu.popup.popup_creator import PopupCreator
from ooodev.utils.kind.module_names_kind import ModuleNamesKind
if TYPE_CHECKING:
from com.sun.star.awt import MenuEvent
from ooodev.gui.menu.popup_menu import PopupMenu
def on_menu_select(src: Any, event: EventArgs, menu: PopupMenu) -> None:
print("Menu Selected")
me = cast("MenuEvent", event.event_data)
print("MenuId", me.MenuId)
command = menu.get_command(me.MenuId)
if command:
print("Command", command)
# check if command is a dispatch command
if menu.is_dispatch_cmd(command):
menu.execute_cmd(command)
def get_popup_menu() -> list:
new_menu = [
{"command": ".uno:Cut", "module": ModuleNamesKind.SPREADSHEET_DOCUMENT},
{"command": ".uno:Copy", "module": ModuleNamesKind.SPREADSHEET_DOCUMENT},
{"command": ".uno:Paste", "module": ModuleNamesKind.SPREADSHEET_DOCUMENT},
{
"text": "Paste Special",
"command": ".uno:PasteSpecialMenu",
"submenu": [
{
# "text": "Paste Unformatted",
"command": ".uno:PasteUnformatted",
"module": ModuleNamesKind.SPREADSHEET_DOCUMENT,
},
{"text": "-"},
{"text": "My Paste Only Text", "command": ".uno:PasteOnlyText", "module": ModuleNamesKind.NONE},
{"text": "Paste Only Text", "command": ".uno:PasteOnlyValue"},
{"text": "Paste Only Formula", "command": ".uno:PasteOnlyFormula"},
{"text": "-"},
{"text": "Paste Transposed", "command": ".uno:PasteTransposed"},
{"text": "-"},
{
"command": ".uno:PasteSpecial",
"module": ModuleNamesKind.SPREADSHEET_DOCUMENT,
},
],
},
{"text": "-"},
{"text": "Data Select", "command": ".uno:DataSelect"},
{"text": "Current Validation", "command": ".uno:CurrentValidation"},
{"text": "Define Current Name", "command": ".uno:DefineCurrentName"},
{"text": "-"},
{"text": "Insert cells", "command": ".uno:InsertCell"},
{"text": "Del cells", "command": ".uno:DeleteCell"},
{"text": "Delete", "command": ".uno:Delete"},
{"text": "Merge Cells", "command": ".uno:MergeCells"},
{"text": "Split Cell", "command": ".uno:SplitCell"},
{"text": "-"},
{"text": "Format Paintbrush", "command": ".uno:FormatPaintbrush"},
{"text": "Reset Attributes", "command": ".uno:ResetAttributes"},
{
"text": "Format Styles Menu",
"command": ".uno:FormatStylesMenu",
"submenu": [
{"text": "Edit Style", "command": ".uno:EditStyle"},
{"text": "-"},
{
"text": "Default Cell Styles",
"command": ".uno:DefaultCellStylesmenu",
"style": MenuItemStyleEnum.RADIOCHECK,
},
{
"text": "Accent1 Cell Styles",
"command": ".uno:Accent1CellStyles",
"style": MenuItemStyleEnum.RADIOCHECK,
},
{
"text": "Accent2 Cell Styles",
"style": MenuItemStyleEnum.RADIOCHECK,
},
{
"text": "Accent 3 Cell Styles",
"command": ".uno:Accent3CellStyles",
"style": MenuItemStyleEnum.RADIOCHECK,
},
{"text": "-"},
{"text": "Bad Cell Styles", "command": ".uno:BadCellStyles", "style": MenuItemStyleEnum.RADIOCHECK},
{
"text": "Error Cell Styles",
"command": ".uno:ErrorCellStyles",
"style": MenuItemStyleEnum.RADIOCHECK,
},
{"text": "Good Cell Styles", "command": ".uno:GoodCellStyles", "style": MenuItemStyleEnum.RADIOCHECK},
{
"text": "Neutral Cell Styles",
"command": ".uno:NeutralCellStyles",
"style": MenuItemStyleEnum.RADIOCHECK,
},
{
"text": "Warning Cell Styles",
"command": ".uno:WarningCellStyles",
"style": MenuItemStyleEnum.RADIOCHECK,
},
{
"text": "-",
},
{
"text": "Footnote Cell Styles",
"command": ".uno:FootnoteCellStyles",
"style": MenuItemStyleEnum.RADIOCHECK,
},
{"text": "Note Cell Styles", "command": ".uno:NoteCellStyles", "style": MenuItemStyleEnum.RADIOCHECK},
],
},
{"text": "-"},
{"text": "Insert Annotation", "command": ".uno:InsertAnnotation"},
{"text": "Edit Annotation", "command": ".uno:EditAnnotation"},
{"text": "Delete Note", "command": ".uno:DeleteNote"},
{"text": "Show Note", "command": ".uno:ShowNote"},
{"text": "Hide Note", "command": ".uno:HideNote"},
{"text": "-"},
{"text": "Format Sparkline", "command": ".uno:FormatSparklineMenu"},
{"text": "-"},
{"command": ".uno:CurrentConditionalFormatDialog", "module": ModuleNamesKind.SPREADSHEET_DOCUMENT},
{
"text": "Current Conditional Format Manager Dialog ...",
"command": ".uno:CurrentConditionalFormatManagerDialog",
},
{"text": "Format Cell Dialog ...", "command": ".uno:FormatCellDialog"},
]
return new_menu
def main():
loader = Lo.load_office(connector=Lo.ConnectPipe())
doc = CalcDoc.create_doc(loader=loader, visible=True)
try:
creator = PopupCreator()
menus = get_popup_menu()
pm = creator.create(menus)
pm.subscribe_all_item_selected(on_menu_select)
rect = Rectangle(100, 100, 100, 100)
doc.activate()
pm.execute(doc.get_frame().ComponentWindow, rect, 0)
# place a breakpoint here to inspect the menu
assert pm
finally:
doc.close()
Lo.close_office()
if __name__ == "__main__":
main()
Command Values
The CmdInfo
class (see Getting Info UNO on Commands) makes it possible to look up command information.
There are few ways to do this.
Auto Command Values
On way is to just use the build in ability of the PopupCreator
class.
# auto command entry.
{"command": ".uno:Cut", "module": ModuleNamesKind.SPREADSHEET_DOCUMENT},
Auto command entries are created by including the module
key in a menu entry.
This instructs PopupCreator
to get the information by looking up the command information using CmdInfo
to fill in other popup information.
Note not every command has an entry in the sources that CmdInfo
pull from.
The Command Data for .uno:Cut
is as follows:
CmdData(
command='.uno:Copy',
label='Cop~y',
name='Copy',
popup=False,
properties=1,
popup_label='',
tooltip_label='',
target_url='',
is_experimental=False,
module_hotkey='',
global_hotkey='Ctrl+C'
)
Manual Command Lookup
It is also possible to lookup command info manually. A few modification to the example code:
def get_cmd_data(cmd: str, mod_kind: str | ModuleNamesKind) -> CmdData | None:
# CmdInfo() is a singleton.
return CmdInfo().get_cmd_data(mode_name=mod_kind, cmd=cmd)
def get_calc_command_text(cmd: str, default: str) -> str:
cmd_data = get_cmd_data(cmd, ModuleNamesKind.SPREADSHEET_DOCUMENT)
if cmd_data is not None:
return cmd_data.label or cmd_data.name
else:
return default
def main():
# ...
creator = PopupCreator()
menus = get_popup_menu()
pm = creator.create(menus)
# other code
Entries in the menu can now use the get_calc_command_text()
method to lookup names for commands.
{"text": get_calc_command_text(".uno:InsertCell", "Insert cells"), "command": ".uno:InsertCell"},
Events
Export/Import Json
A menu can be loaded and saved from json data.
The json data must have root attribute of id
that has a value of ooodev.popup_menu
to be considered valid.
The root attribute version
is optional and is the version
of OooDev that the menus was created with.
Saving
Save as Dynamic
Saves the JSON seen in Sample Popup Menu JSON Dynamic Data.
def main():
# ...
creator = PopupCreator()
menus = get_popup_menu()
json_str = creator.json_dumps(menus, dynamic=True)
with open("popup_menu.json", "w") as f:
f.write(json_str)
Save as Normal
Save the JSON see in Sample Popup Menu JSON Normal Data.
def main():
# ...
creator = PopupCreator()
menus = get_popup_menu()
json_str = creator.json_dumps(menus, dynamic=False)
with open("popup_menu.json", "w") as f:
f.write(json_str)
Load JSON
Load File
def main():
# ...
creator = PopupCreator()
menus = PopupCreator.json_load("popup_menu.json")
pm = creator.create(menus)
pm.subscribe_all_item_selected(on_menu_select)
rect = Rectangle(100, 100, 100, 100)
doc.activate()
pm.execute(doc.get_frame().ComponentWindow, rect, 0)
# ...
Load String
def main():
# ...
creator = PopupCreator()
json_str = get_json_str()
menus = PopupCreator.json_loads(json_str)
pm = creator.create(menus)
pm.subscribe_all_item_selected(on_menu_select)
rect = Rectangle(100, 100, 100, 100)
doc.activate()
pm.execute(doc.get_frame().ComponentWindow, rect, 0)
# ...