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

Could do with an example or two! #6

Open
ticky opened this issue Nov 6, 2020 · 3 comments
Open

Could do with an example or two! #6

ticky opened this issue Nov 6, 2020 · 3 comments

Comments

@ticky
Copy link

ticky commented Nov 6, 2020

Hi there, I’ve found this crate while trying to use some parts of NSFileManager from Rust, and I think this crate might do what I want, but given there’s no example code in the docs, nor any example code provided in the repo, and it looks like the feature flags are shielding all the actual API from docs.rs, I’m not really clear on how this works or what it even can do.

A couple of little examples of how to actually use the crate, or a link to a project which does, would help immensely! ✌🏼

@nvzqz
Copy link
Owner

nvzqz commented Nov 6, 2020

Hey, thanks for your interest in this project! 🙂

Unfortunately I haven't yet wrapped the NSFileManager API. If you'd like to implement some parts of it, I'm more than happy to accept a PR. What parts of its API were you looking to use?

This crate is still very much a work-in-progress. However, because I'd like to use some Cocoa APIs from Rust in some other projects, I'll find time to get it to a more featureful state. That said, the API surface I want to eventually cover is huge, so community contribution would be very helpful here.

Regarding docs.rs, I'm able to see all of the documentation at https://docs.rs/fruity. Perhaps you clicked on an unreleased 0.3 item in the README?

@ticky
Copy link
Author

ticky commented Nov 6, 2020

That’s totally fair, but as someone who’s more experienced with Rust than Obj-C stuff specifically, there isn’t really enough in the docs to get started. Perhaps that’s more an indicator that this does a small subset of things someone might want to do at this point?

Either way, a basic example showing constructing and using an instance of something that is already wrapped, and perhaps also some pointers on how one would go about wrapping new stuff, would go a long way!

@simonbuchan
Copy link

I've had some luck with this, perhaps it could be a start?

pub fn run() {
    use fruity::nsstring;
    use app_kit::*;

    let app = NSApplication::sharedApplication();
    assert_eq!(app.as_ptr(), unsafe { NSApp.as_ptr() });

    app.setActivationPolicy_(0); // regular

    // Can't inline or `bar` gets collected after the statement, which crashes on app.run().
    let bar = NSStatusBar::systemStatusBar();
    let item = bar.statusItemWithLength_(-1.0);

    item.setTitle_(nsstring!("Hello, world!"));

    let window = NSWindow::alloc();
    window.initWithContentRect_styleMask_backing_defer_(
        NSRect {
            origin: NSPoint::default(),
            size: NSSize { width: 800.0, height: 600.0 },
        },
        0b1111, // titled, closable, miniturizable, resizable
        2, // buffered,
        1, // YES
    );
    window.setTitle_(nsstring!("My example window!"));
    window.makeKeyAndOrderFront_(None);

    app.run();
}

macro_rules! objc {
    (@class $ident: ident) => {
        #[derive(Clone, Debug)]
        #[repr(C)]
        pub struct $ident(::fruity::objc::id);

        impl ::std::ops::Deref for $ident {
            type Target = ::fruity::objc::id;

            #[inline]
            fn deref(&self) -> &Self::Target {
                &self.0
            }
        }

        impl $ident {
            #[inline]
            pub fn class() -> &'static ::fruity::objc::Class {
                ::paste::paste! {
                    extern "C" {
                        #[link_name = "OBJC_CLASS_$_" $ident]
                        static CLASS: ::fruity::objc::Class;
                    }
                }
                unsafe { &CLASS }
            }
        }
    };
    ($class: ty: + ($ret: ty) $ident: ident) => {
        impl $class {
            pub fn $ident() -> $ret {
                extern "C" { fn objc_msgSend(obj: &::fruity::objc::Class, sel: ::fruity::objc::SEL) -> $ret; }
                let sel = ::fruity::selector!($ident);
                unsafe { objc_msgSend(Self::class(), sel) }
            }
        }
    };
    ($class: ty: + ($ret: ty) $($ident: ident: $arg: ty),+) => {
        ::paste::paste! {
            impl $class {
                pub fn [<$($ident _)+>]($($ident: $arg),+) -> $ret {
                    extern "C" { fn objc_msgSend(obj: &::fruity::objc::Class, sel: ::fruity::objc::SEL, $($ident: $arg),+) -> $ret; }
                    let sel = ::fruity::selector!($ident);
                    unsafe { objc_msgSend(Self::class(), sel, $($ident),+) }
                }
            }
        }
    };
    ($class: ty: - ($ret: ty) $ident: ident) => {
        impl $class {
            pub fn $ident(&self) -> $ret {
                extern "C" { fn objc_msgSend(obj: &::fruity::objc::Object, sel: ::fruity::objc::SEL) -> $ret; }
                let sel = ::fruity::selector!($ident);
                unsafe { objc_msgSend(self, sel) }
            }
        }
    };
    ($class: ty: - ($ret: ty) $($ident: ident: $arg: ty),+) => {
        ::paste::paste! {
            impl $class {
                pub fn [<$($ident _)+>](&self, $($ident: $arg),+) -> $ret {
                    extern "C" { fn objc_msgSend(obj: &::fruity::objc::Object, sel: ::fruity::objc::SEL, $($ident: $arg),+) -> $ret; }
                    let sel = ::fruity::selector!($($ident:)+);
                    unsafe { objc_msgSend(self, sel, $($ident),+) }
                }
            }
        }
    };
}


mod app_kit {
    use fruity::{nsstring, foundation::NSString, objc::{BOOL, Object}};

    objc!(@class NSRunningApplication);
    objc!(@class NSApplication);
    objc!(NSApplication: + (NSApplication) sharedApplication);
    objc!(NSApplication: - (()) run);
    objc!(NSApplication: - (i32) activationPolicy);
    objc!(NSApplication: - (BOOL) setActivationPolicy: i32);
    objc!(@class NSStatusBar);
    objc!(@class NSStatusItem);
    objc!(NSStatusBar: + (NSStatusBar) systemStatusBar);
    objc!(NSStatusBar: - (NSStatusItem) statusItemWithLength: f64);
    objc!(NSStatusItem: - (()) setTitle: ::fruity::foundation::NSString);
    objc!(@class NSWindow);
    objc!(NSWindow: + (NSWindow) alloc);

    #[repr(C)]
    #[derive(Default, Debug)]
    pub struct NSPoint {
        pub x: f64,
        pub y: f64,
    }
    #[repr(C)]
    #[derive(Default, Debug)]
    pub struct NSSize {
        pub width: f64,
        pub height: f64,
    }
    #[repr(C)]
    #[derive(Default, Debug)]
    pub struct NSRect {
        pub origin: NSPoint,
        pub size: NSSize,
    }
    objc!(NSWindow: - (NSWindow) initWithContentRect: NSRect, styleMask: u32, backing: u32, defer: BOOL);
    objc!(NSWindow: - (NSString) title);
    objc!(NSWindow: - (()) setTitle: NSString);
    objc!(NSWindow: - (()) display);
    objc!(NSWindow: - (()) makeKeyAndOrderFront: Option<&Object>);

    extern "C" {
        pub static NSApp: NSApplication;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants