use super::thread_future::ThreadFuture;
use crate::dialog::{MessageButtons, MessageDialog, MessageLevel};
use winapi::um::winuser::{
MessageBoxW, IDOK, IDYES, MB_ICONERROR, MB_ICONINFORMATION, MB_ICONWARNING, MB_OK, MB_OKCANCEL,
MB_YESNO,
};
use std::{ffi::OsStr, iter::once, os::windows::ffi::OsStrExt, ptr};
pub struct WinMessageDialog {
text: Vec<u16>,
caption: Vec<u16>,
flags: u32,
}
impl WinMessageDialog {
pub fn new(opt: MessageDialog) -> Self {
let input = format!("{}\n{}", opt.title, opt.description);
let text: Vec<u16> = OsStr::new(&input).encode_wide().chain(once(0)).collect();
let caption: Vec<u16> = OsStr::new(&opt.title)
.encode_wide()
.chain(once(0))
.collect();
let level = match opt.level {
MessageLevel::Info => MB_ICONINFORMATION,
MessageLevel::Warning => MB_ICONWARNING,
MessageLevel::Error => MB_ICONERROR,
};
let buttons = match opt.buttons {
MessageButtons::Ok => MB_OK,
MessageButtons::OkCancel => MB_OKCANCEL,
MessageButtons::YesNo => MB_YESNO,
};
Self {
text,
caption,
flags: level | buttons,
}
}
pub fn run(self) -> bool {
let ret = unsafe {
MessageBoxW(
ptr::null_mut(),
self.text.as_ptr(),
self.caption.as_ptr(),
self.flags,
)
};
ret == IDOK || ret == IDYES
}
pub fn run_async(self) -> ThreadFuture<bool> {
ThreadFuture::new(move |data| *data = Some(self.run()))
}
}
use crate::backend::MessageDialogImpl;
impl MessageDialogImpl for MessageDialog {
fn show(self) -> bool {
let dialog = WinMessageDialog::new(self);
dialog.run()
}
}
use crate::backend::AsyncMessageDialogImpl;
use crate::backend::DialogFutureType;
impl AsyncMessageDialogImpl for MessageDialog {
fn show_async(self) -> DialogFutureType<bool> {
let dialog = WinMessageDialog::new(self);
Box::pin(dialog.run_async())
}
}