question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Description

Although this question is not strictly about pywebview if I can get some help I could write a guide with the code or even work with a PR in the future if there is interest.

I have seen that a menu bar is quite required for my app (ex. File > Open, File > Save, Edit > …). Although I plan to release it in the three platforms, I am starting with Mac, which let me try to hijack the Cocoa’s BrowserView._add_view_menu to add simple menu items that would ultimately just call a custom python function.

I have never touched PyObjC. Just mimicking the existing code I can create new menus myMenu.addItemWithTitle_action_keyEquivalent_("full", "foobar:", "o") but I don’t know how to do it to execute my python function (I understand I need to add a foobar_() function somewhere…). PyObjC guides / example code have not helped me, as there are differences between the ones I have seen and your implementation. Could I get some help?

I understand in Linux / Windows this task will less cryptic?

Thank you!

Btw, amazing tool you have here 😃

Practicalities

  • YES I am willing to work on this issue myself.
  • NO I am prepared to support this issue financially.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:10 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
bustawincommented, Apr 21, 2020

I have been able to create a working menu 😃

Now the problem is that I don’t know how to relate the menu to the active window. For now, the menu is global. So if I click “save” and I have several windows I don’t know which window to save. Ideally the my_action() should receive a window argument to know which window executed it. Any idea how to get it?

from __future__ import annotations

import typing as t

import AppKit
import objc
from webview.platforms.cocoa import BrowserView


def add_view(self: BrowserView):
    super_view_menu(self)

    m = Menu("File", parent=self.app.mainMenu())
    m.action("First item", my_action, command="F")
    (
        m.sub_menu("Second item")
        .action("First sub item", my_action)
        .separator()
        .action("Second sub item", my_action, command="R")
    )


super_view_menu = BrowserView._add_view_menu
BrowserView._add_view_menu = add_view


def my_action():
    print("executed!")


class Menu:
    def __init__(self, title: str, parent: t.Union[Menu, "NSMenu"]):
        self.m = AppKit.NSMenu.alloc().init()
        self.item = AppKit.NSMenuItem.alloc().init()
        self.item.setSubmenu_(self.m)
        if not isinstance(parent, self.__class__):
            self.m.setTitle_(title)
            parent.addItem_(self.item)
        else:
            self.item.setTitle_(title)
            parent.m.addItem_(self.item)

    def action(self, title: str, action: callable, command: t.Optional[str] = None):
        Action(self, title, action, command)
        return self

    def separator(self):
        self.m.addItem_(AppKit.NSMenuItem.separatorItem())
        return self

    def sub_menu(self, title: str):
        return self.__class__(title, parent=self)


class Action:
    def __init__(self, parent: Menu, title: str, action: callable, command=None):
        self.action = action
        s = objc.selector(self._call_action, signature=b"v@:")
        if command:
            item = parent.m.addItemWithTitle_action_keyEquivalent_(title, s, command)
        else:
            item = AppKit.NSMenuItem.alloc().init()
            item.setAction_(s)
            item.setTitle_(title)
            parent.m.addItem_(item)
        item.setTarget_(self)

    def _call_action(self):
        self.action()



3reactions
r0x0rcommented, Apr 14, 2020

Objective C is confusing af and can be intimidating. PyObjC adds its own quirks, but the good news is that it mostly works, once you get the syntax. As for the menu, somebody else has implemented it, so myself I have only a vague idea how it should be done. addItemWithTitle_action_keyEquivalent_ seems to be the right method and action is attached via a selector. Here is an example of how to use a selector in Python. https://lethain.com/how-to-use-selectors-in-pyobjc/

The menubar has been requested several times and in my opinion it can be incorporated into pywebview. If you would like to extend your work into a generic solution, that would be most welcomed. The scaffold for the API would be something like this

menu_items = {
  'File': (
    ('First item', action),
    (), // separator
    ('Second item', action2),
  )
  'Edit': ( ....)
}
menu = webview.create_menu(menu_items)
window = webview.create_window('Window with menu', menu=menu)
Read more comments on GitHub >

github_iconTop Results From Across the Web

Free Bar Menu Templates and Designs - MustHaveMenus
Use our free bar menu templates to showcase your cocktails, mixed drinks, and other bar items. Each professionally-designed menu is fully customizable in ......
Read more >
83 Bar Menus ideas | bar menu, menu, menu design
Mar 23, 2021 - Explore Argos Inn's board "Bar Menus" on Pinterest. See more ideas about bar menu, menu, menu design.
Read more >
Free printable and customizable bar menu templates - Canva
Design an intoxicating bar menu with free and printable bar menu templates from Canva that are easy to customize.
Read more >
Ideas to Inspire Your Bar Menu's Design - Toast
A strong bar menu is made up of more than delicious bites and a drink menu. Great design, an evolving drink list, and...
Read more >
Bar Menus - Zazzle
Bar Menus. 쎂Previous. bar×; table weddings; minimalist; alcohol; boho wedding business signs; minimalist bar signs; boho drink weddings; signature drinks
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found