예제 #1
0
def _init() -> None:
    main_window = get_main_window()
    main_window.config(menu=tkinter.Menu(main_window, tearoff=False))
    main_window.bind('<<PluginsLoaded>>',
                     (lambda event: update_keyboard_shortcuts()),
                     add=True)
    main_window.bind_class('Text',
                           '<FocusIn>',
                           _fix_text_widget_bindings,
                           add=True)
    _fill_menus_with_default_stuff()
예제 #2
0
def _update_shortcuts_for_opening_submenus() -> None:
    used_letters = set()
    for virtual_event in get_main_window().event_info():
        for physical_event in get_main_window().event_info(virtual_event):
            match = re.fullmatch(r"<Alt-Key-([a-z])>", physical_event)
            if match is not None:
                used_letters.add(match.group(1))

    menu = get_menu(None)
    for submenu_index in range(menu.index("end") +
                               1):  # type: ignore[no-untyped-call]
        for letter_index, letter in enumerate(
                menu.entrycget(
                    submenu_index,
                    "label").lower()):  # type: ignore[no-untyped-call]
            if letter in ascii_lowercase and letter not in used_letters:
                menu.entryconfig(submenu_index, underline=letter_index)
                used_letters.add(letter)
                break
        else:
            menu.entryconfig(submenu_index, accelerator="")
예제 #3
0
def _init() -> None:
    log.debug("_init() starts")
    main_window = get_main_window()
    main_window.config(menu=tkinter.Menu(main_window, tearoff=False))
    main_window.bind("<<PluginsLoaded>>",
                     (lambda event: update_keyboard_shortcuts()),
                     add=True)
    main_window.bind_class("Text",
                           "<FocusIn>",
                           _fix_text_widget_bindings,
                           add=True)
    _fill_menus_with_default_stuff()
    log.debug("_init() done")
예제 #4
0
def _update_keyboard_shortcuts_inside_submenus() -> None:
    main_window = get_main_window()
    for path, menu, index in _walk_menu_contents():
        event_name = f"<<Menubar:{path}>>"

        # show keyboard shortcuts in menus
        menu.entryconfig(index,
                         accelerator=utils.get_binding(event_name, menu=True))

        # trigger menu items when <<Menubar:Foo/Bar>> events are generated
        if not main_window.bind(event_name):
            # FIXME: what if menu item is inserted somewhere else than to end, and indexes change?
            command = functools.partial(_menu_event_handler, menu, index)
            main_window.bind(event_name, command, add=True)
예제 #5
0
def get_menu(path: Optional[str]) -> tkinter.Menu:
    """
    Find a menu widget, creating menus as necessary.

    For example, ``get_menu("Tools/Python")`` returns a submenu labelled
    *Python* from a menu named *Tools*. The *Tools* menu is created if it
    doesn't already exist.

    If *path* is ``None``, then the menubar itself is returned.
    """
    main_window = get_main_window()
    main_menu = cast(tkinter.Menu,
                     main_window.nametowidget(main_window.cget('menu')))
    if path is None:
        return main_menu

    menu = main_menu
    for label in path.split('/'):
        submenu_index = _find_item(menu, label)
        if submenu_index is None:
            # Need to pass the menu as an explicit argument to tkinter.Menu.
            # Otherwise add_cascade() below tries to allocate a crazy amount of
            # memory and freezes everything when running tests (don't know why)
            submenu = tkinter.Menu(menu, tearoff=False)
            if menu == main_menu and menu.index('end') is not None:
                # adding something to non-empty main menu, don't add all the
                # way to end so that "Help" menu stays at very end
                last_index = menu.index("end")
                assert last_index is not None
                menu.insert_cascade(last_index, label=label, menu=submenu)
            else:
                menu.add_cascade(label=label, menu=submenu)
            menu = submenu

        else:
            menu = cast(
                tkinter.Menu,
                menu.nametowidget(menu.entrycget(submenu_index, 'menu')))

    return menu
예제 #6
0
def update_keyboard_shortcuts() -> None:
    """
    This function does two things to the *New File* menu item in the *File*
    menu, and similarly to all other menu items in all menus:

        * Show *Ctrl+N* next to *New File*.
        * Ensure that the menu item's callback runs when Ctrl+N is pressed.

    This has to be called when menus or keyboard shortcuts have been modified.
    It's called automatically when plugins have been set up.
    """
    main_window = get_main_window()
    for path, menu, index in _walk_menu_contents():
        event_name = f'<<Menubar:{path}>>'

        # show keyboard shortcuts in menus
        shortcuts = map(_get_keyboard_shortcut,
                        main_window.event_info(event_name))
        menu.entryconfig(index, accelerator=', '.join(shortcuts))

        # trigger menu items when <<Menubar:Foo/Bar>> events are generated
        if not main_window.bind(event_name):
            command = functools.partial(_menu_event_handler, menu, index)
            main_window.bind(event_name, command, add=True)
예제 #7
0
def _generate_event(name: str, junk: object) -> Literal["break"]:
    get_main_window().event_generate(name)
    return "break"