use super::{Op, PathBuf};
use crate::platform::native::objc::{Id, class, msg, nsstring, with_pool};
use std::ffi::{CStr, OsStr, c_char};
use std::os::unix::ffi::OsStrExt;
const MODAL_RESPONSE_OK: isize = 1;
unsafe fn url_path(url: Id) -> Option<PathBuf> {
if url.is_null() {
return None;
}
let p = unsafe { msg!(url, "fileSystemRepresentation", () -> *const c_char) };
if p.is_null() {
return None;
}
let bytes = unsafe { CStr::from_ptr(p) }.to_bytes();
Some(PathBuf::from(OsStr::from_bytes(bytes)))
}
pub(super) fn file_chooser(op: Op, title: &str) -> Option<PathBuf> {
with_pool(|| unsafe {
let _ = msg!(class("NSApplication"), "sharedApplication", () -> Id);
let panel = match op {
Op::Save => msg!(class("NSSavePanel"), "savePanel", () -> Id),
Op::Open | Op::Folder => msg!(class("NSOpenPanel"), "openPanel", () -> Id),
};
if panel.is_null() {
return None;
}
let text = nsstring(title);
msg!(panel, "setTitle:", (text: Id) -> ());
msg!(panel, "setMessage:", (text: Id) -> ());
let yes = true;
msg!(panel, "setCanCreateDirectories:", (yes: bool) -> ());
if op != Op::Save {
let files = op == Op::Open;
let dirs = op == Op::Folder;
let multiple = false;
msg!(panel, "setCanChooseFiles:", (files: bool) -> ());
msg!(panel, "setCanChooseDirectories:", (dirs: bool) -> ());
msg!(panel, "setAllowsMultipleSelection:", (multiple: bool) -> ());
}
if msg!(panel, "runModal", () -> isize) != MODAL_RESPONSE_OK {
return None;
}
let url = match op {
Op::Open | Op::Folder => {
let urls = msg!(panel, "URLs", () -> Id);
if urls.is_null() {
return None;
}
msg!(urls, "firstObject", () -> Id)
}
Op::Save => msg!(panel, "URL", () -> Id),
};
url_path(url)
})
}