1use nifty_runtime::{DialogKind, Failure, FileDialog, Picked};
5
6use crate::abi::borrow_context;
7use crate::context::{AppError, Context};
8use crate::place::{Location, PlaceDesc};
9use crate::value::{self, LIST_OF_STRINGS, STRING, Slot};
10
11#[derive(Debug)]
14pub(crate) struct Answer {
15 place: Location,
16 kind: DialogKind,
17 span: u32,
18}
19
20impl Context {
21 pub(crate) fn answer_dialog(&self, answer: &Answer, picked: Picked) -> Result<(), AppError> {
24 let fail = |failure| self.error(&failure, answer.span);
25 let paths = match picked {
26 Picked::Chosen(paths) => paths,
27 Picked::Cancelled => return Ok(()),
28 Picked::Failed(reason) => return Err(fail(Failure::Dialog(reason))),
29 };
30 let written = if answer.kind.picks_many() {
31 self.write_location(&answer.place, value::strings_slot(paths), &LIST_OF_STRINGS)
32 } else {
33 let path = paths
34 .into_iter()
35 .next()
36 .expect("backends answer a one-path dialog with exactly one path");
37 self.write_location(&answer.place, value::string_slot(path), &STRING)
38 };
39 written.map_err(fail)
40 }
41}
42
43#[unsafe(no_mangle)]
50pub(crate) unsafe extern "C" fn nf_pick(
51 context: *const Context,
52 kind: DialogKind,
53 answer: &PlaceDesc,
54 title: Slot,
55 types: Slot,
56 folder: Slot,
57 name: Slot,
58 span: u32,
59) -> bool {
60 let context = unsafe { borrow_context(context) };
62 let place = unsafe { Location::from_place(answer) };
64 let types: Vec<&str> = value::as_list(types)
65 .items
66 .iter()
67 .map(|item| value::as_str(*item))
68 .collect();
69 let asked = place.and_then(|place| {
70 let dialog = FileDialog::new(
71 kind,
72 value::as_str(title).to_owned(),
73 &types,
74 value::as_str(folder),
75 value::as_str(name).to_owned(),
76 )
77 .map_err(|error| Failure::Dialog(error.to_string()))?;
78 Ok((dialog, Answer { place, kind, span }))
79 });
80 match asked {
81 Ok((dialog, answer)) => {
82 context.ask_dialog(dialog, answer);
83 true
84 }
85 Err(failure) => {
86 context.fail(failure, span);
87 false
88 }
89 }
90}
91
92#[unsafe(no_mangle)]
97pub(crate) unsafe extern "C" fn nf_fail_dialog_into_variable(context: *const Context, span: u32) {
98 unsafe { borrow_context(context) }.fail(Failure::DialogIntoVariable, span);
100}