ryanmcgrath / cacao

Rust bindings for AppKit (macOS) and UIKit (iOS/tvOS). Experimental, but working!
MIT License
1.8k stars 65 forks source link

Please add NSOpenGLView #70

Open dagit opened 1 year ago

dagit commented 1 year ago

I tried to do this in my project code but it seems like I need access to ObjcAccess in order to write a Layout impl. It seems like maybe new widgets need to be wrapped directly in cacao or certain interfaces would need to be made public?

I just want a way to render to an OpenGL area from within a program that I was thinking of writing in cacao. I don't really know the API well enough, but looking at the image example it seemed like maybe I need to use add_subview or set_content_view passing the wrapper I made for NSOpenGLView? That's the point where I run into the issue that I can't write a Layout impl.

ryanmcgrath commented 1 year ago

You have a very good point here - ObjcAccess could probably be public with no issues. It's important that people be able to experiment without needing to extend the core cacao framework itself.

If you want to PR that change and test whether it allows you to do what you need, definitely feel free - otherwise I'll leave this open and get to it for the next release.

siketyan commented 1 year ago

@dagit

76 got merged and now you can use the custom view by implementing ObjAccess and Layout traits. This is an example of using VZVirtualMachineView, in combination of virtualization-rs ^1:

use cacao::foundation::id;
use cacao::layout::Layout;
use cacao::objc_access::ObjcAccess;
use objc::rc::StrongPtr;
use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use virtualization_rs::virtualization::virtual_machine::VZVirtualMachine;

#[derive(Clone)]
pub struct VZVirtualMachineView(StrongPtr);

impl VZVirtualMachineView {
    pub fn new() -> Self {
        Self(unsafe { StrongPtr::new(msg_send![class!(VZVirtualMachineView), new]) })
    }

    pub fn set_virtual_machine(&self, vm: &VZVirtualMachine) {
        println!("{:?}", unsafe { vm.id() });
        let _: () = unsafe { msg_send![*self.0, setVirtualMachine: vm.id()] };
    }
}

impl Default for VZVirtualMachineView {
    fn default() -> Self {
        Self::new()
    }
}

impl ObjcAccess for VZVirtualMachineView {
    fn with_backing_obj_mut<F: Fn(id)>(&self, handler: F) {
        handler(*self.0)
    }

    fn get_from_backing_obj<F: Fn(&Object) -> R, R>(&self, handler: F) -> R {
        handler(unsafe { &**self.0 })
    }
}

impl Layout for VZVirtualMachineView {}