///|
/// Native multi-path dialogs write their selections into a larger fixed buffer.
const MULTI_PATH_DIALOG_BUFFER_SIZE : Int = 262144
///|
/// Show a native multi-file dialog and write serialized paths into `path_out`.
#borrow(title, directory, filters, path_out)
extern "c" fn open_files_dialog_ffi(
title : Bytes,
directory : Bytes,
filters : Bytes,
path_out : Bytes,
path_out_len : Int,
) -> Int = "moonbit_dialog_open_files"
///|
/// Decode a raw native multi-path dialog status and selected paths.
fn decode_multi_path_dialog_outcome(
platform : Platform,
raw : Int,
path_out : Bytes,
) -> Result[MultiPathDialogOutcome, DialogError] {
match decode_status_error(platform, raw) {
Some(error) => Err(error)
None =>
match backend_from_success(raw) {
Some(backend) =>
match path_dialog_kind_from_success(raw) {
PATH_DIALOG_SELECTED_CODE =>
Ok({ backend, selection: Selected(decode_path_list(path_out)) })
PATH_DIALOG_CANCELLED_CODE => Ok({ backend, selection: Cancelled })
_ => Err(UnsupportedPlatform(platform))
}
None => Err(UnsupportedPlatform(platform))
}
}
}
///|
/// Run a multi-path dialog callback for a known platform and decode the result.
fn run_multi_path_dialog_request_for_platform(
platform : Platform,
callback : (Bytes) -> Int,
) -> Result[MultiPathDialogOutcome, DialogError] {
let path_out = Bytes::new(MULTI_PATH_DIALOG_BUFFER_SIZE)
let raw_result = callback(path_out)
decode_multi_path_dialog_outcome(platform, raw_result, path_out)
}
///|
/// Run a multi-path dialog callback and decode its raw native result.
fn run_multi_path_dialog_request(
callback : (Bytes) -> Int,
) -> Result[MultiPathDialogOutcome, DialogError] {
match supported_platform_result() {
Ok(platform) =>
run_multi_path_dialog_request_for_platform(platform, callback)
Err(error) => Err(error)
}
}
///|
/// Show a multi-file open request through the native FFI and decode the result.
fn show_open_files_request(
title : String,
directory : String,
filters : Array[FileFilter],
) -> Result[MultiPathDialogOutcome, DialogError] {
let encoded_filters = encode_file_filters(filters)
run_multi_path_dialog_request(path_out => {
open_files_dialog_ffi(
encode_utf8_bytes(title),
encode_utf8_bytes(directory),
encoded_filters,
path_out,
path_out.length(),
)
})
}