Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to pass a Rust function as a selector? #614

Open
ghostman2013 opened this issue May 6, 2024 · 2 comments
Open

How to pass a Rust function as a selector? #614

ghostman2013 opened this issue May 6, 2024 · 2 comments
Labels
A-framework Affects the framework crates and the translator for them question Further information is requested

Comments

@ghostman2013
Copy link

ghostman2013 commented May 6, 2024

Hello!

I use a little modified code that's based on examples from objc2-app-kit crate sources:

impl AppDelegate {
    fn new(mtm: MainThreadMarker, menu: Option<Menu>) -> Id<Self> {
        let this = mtm.alloc();
        let this = this.set_ivars(Ivars {
            mtm,
            menu,
        });
        unsafe { msg_send_id![super(this), init] }
    }

    fn build_menu(&self, menu: &Menu, ns_menu: &Id<NSMenu>) {
        let ivars = self.ivars();
        for item in menu.items.iter() {
            let ns_menu_item = NSMenuItem::new(ivars.mtm);
            let title = NSString::from_str(&item.name);
            unsafe { ns_menu_item.setTitle(&title) };
            
            if let Some(on_click) = &item.on_click {
                unsafe { ns_menu_item.setAction(Some(on_click)) };
            }

            if let Some(submenu) = &item.submenu {
                let ns_submenu = NSMenu::new(ivars.mtm);
                self.build_menu(submenu, &ns_submenu);
                ns_menu_item.setSubmenu(Some(&ns_submenu));
            }
            
            ns_menu.addItem(&ns_menu_item);
        }
    }

    fn create_menu(&self, application: Id<NSApplication>) {
        let ivars = self.ivars();
        if let Some(menu) = &ivars.menu {
            let main_menu = NSMenu::new(ivars.mtm);
            application.setMainMenu(Some(&main_menu));

            self.build_menu(menu, &main_menu);
        }
    }
}

Just a trivial AppDelegate with menu builder. However, I hit troubles at this step:

if let Some(on_click) = &item.on_click {
    unsafe { ns_menu_item.setAction(Some(on_click)) };
}

The on_click: fn() is a typical Rust function but I can't get how to pass it as a selector, to NSMenuItem called it on click.

Unfortunately, I couldn't find any examples. Could you explain, please, how I can make it?

@madsmtm
Copy link
Owner

madsmtm commented May 6, 2024

This is a common pattern used in Apple's frameworks, see the documentation on Target-Action, and it's a bit of a pain to handle when you're used to Rust's closures.

There's a similar issue here: #585

Try to have a look at that, in short you have to make a method on your delegate with a selector like onClick:, place it on the menu item with .setAction(Some(sel!(onClick:))) and .setTarget(Some(self)), and then you have to run your click handler in onClick:.

I know that's not a real explanation, but I don't have time to write up a full example right now, will do so later.

@ghostman2013
Copy link
Author

ghostman2013 commented May 10, 2024

This is a common pattern used in Apple's frameworks, see the documentation on Target-Action, and it's a bit of a pain to handle when you're used to Rust's closures.

There's a similar issue here: #585

Try to have a look at that, in short you have to make a method on your delegate with a selector like onClick:, place it on the menu item with .setAction(Some(sel!(onClick:))) and .setTarget(Some(self)), and then you have to run your click handler in onClick:.

I know that's not a real explanation, but I don't have time to write up a full example right now, will do so later.

No, you have explained it very clearly. Thank you! I got how to make.

@madsmtm madsmtm added question Further information is requested A-framework Affects the framework crates and the translator for them labels May 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-framework Affects the framework crates and the translator for them question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants