use crate::ResponseType;
#[cfg(windows)]
pub type MsgBoxStyle = windows_sys::Win32::UI::WindowsAndMessaging::MESSAGEBOX_STYLE;
#[cfg(unix)]
pub type MsgBoxStyle = gtk::MessageType;
#[cfg(windows)]
pub type MsgBoxButtonStyle = windows_sys::Win32::UI::WindowsAndMessaging::MESSAGEBOX_STYLE;
#[cfg(unix)]
pub type MsgBoxButtonStyle = gtk::ButtonsType;
#[cfg(windows)]
pub const BS_NONE: MsgBoxButtonStyle = 0;
#[cfg(unix)]
pub const BS_NONE: MsgBoxButtonStyle = gtk::ButtonsType::None;
#[cfg(windows)]
pub const BS_OK: MsgBoxButtonStyle = windows_sys::Win32::UI::WindowsAndMessaging::MB_OK;
#[cfg(unix)]
pub const BS_OK: MsgBoxButtonStyle = gtk::ButtonsType::Ok;
#[cfg(windows)]
pub const BS_YESNO: MsgBoxButtonStyle = windows_sys::Win32::UI::WindowsAndMessaging::MB_YESNO;
#[cfg(unix)]
pub const BS_YESNO: MsgBoxButtonStyle = gtk::ButtonsType::YesNo;
#[cfg(windows)]
pub const BS_OKCANCEL: MsgBoxButtonStyle = windows_sys::Win32::UI::WindowsAndMessaging::MB_OKCANCEL;
#[cfg(unix)]
pub const BS_OKCANCEL: MsgBoxButtonStyle = gtk::ButtonsType::OkCancel;
#[cfg(windows)]
pub const MS_NONE: MsgBoxStyle = 0;
#[cfg(unix)]
pub const MS_NONE: MsgBoxStyle = gtk::MessageType::Other;
#[cfg(windows)]
pub const MS_INFORMATION: MsgBoxStyle =
windows_sys::Win32::UI::WindowsAndMessaging::MB_ICONINFORMATION;
#[cfg(unix)]
pub const MS_INFORMATION: MsgBoxStyle = gtk::MessageType::Info;
#[cfg(windows)]
pub const MS_QUESTION: MsgBoxStyle = windows_sys::Win32::UI::WindowsAndMessaging::MB_ICONQUESTION;
#[cfg(unix)]
pub const MS_QUESTION: MsgBoxStyle = gtk::MessageType::Question;
#[cfg(windows)]
pub const MS_WARNING: MsgBoxStyle = windows_sys::Win32::UI::WindowsAndMessaging::MB_ICONWARNING;
#[cfg(unix)]
pub const MS_WARNING: MsgBoxStyle = gtk::MessageType::Warning;
#[cfg(windows)]
pub const MS_ERROR: MsgBoxStyle = windows_sys::Win32::UI::WindowsAndMessaging::MB_ICONERROR;
#[cfg(unix)]
pub const MS_ERROR: MsgBoxStyle = gtk::MessageType::Error;
#[cfg(windows)]
type Result = windows_sys::Win32::UI::WindowsAndMessaging::MESSAGEBOX_RESULT;
#[cfg(unix)]
type Result = gtk::ResponseType;
pub struct MsgBox {
text: String,
caption: String,
style: MsgBoxStyle,
button_style: MsgBoxButtonStyle,
}
impl MsgBox {
pub fn new(
text: impl Into<String>,
caption: impl Into<String>,
style: MsgBoxStyle,
button_style: MsgBoxButtonStyle,
) -> Self {
Self {
text: text.into(),
caption: caption.into(),
style,
button_style,
}
}
pub fn run(&self) -> ResponseType {
let result =
MsgBox::show_base_dialog(&*self.text, &*self.caption, self.style, self.button_style);
MsgBox::match_response_type(result)
}
#[cfg(windows)]
fn show_base_dialog(
text: &str,
caption: &str,
style: MsgBoxStyle,
button_style: MsgBoxButtonStyle,
) -> Result {
use std::iter::once;
use windows_sys::{
Win32::Foundation::*, Win32::System::Threading::*, Win32::UI::WindowsAndMessaging::*,
};
unsafe {
let event = CreateEventW(std::ptr::null(), 1, 0, std::ptr::null());
SetEvent(event);
WaitForSingleObject(event, 0);
CloseHandle(event);
MessageBoxW(
0,
text.encode_utf16()
.chain(once(0))
.collect::<Vec<u16>>()
.as_mut_ptr(),
caption
.encode_utf16()
.chain(once(0))
.collect::<Vec<u16>>()
.as_mut_ptr(),
style | button_style,
)
}
}
#[cfg(unix)]
fn show_base_dialog(
text: &str,
caption: &str,
style: MsgBoxStyle,
button_style: MsgBoxButtonStyle,
) -> Result {
use gtk::prelude::*;
gtk::init().expect("Failed to initialize gtk.");
let window = gtk::Window::new(gtk::WindowType::Toplevel);
window.set_title(caption);
let dialog = gtk::MessageDialog::new(
Some(&window),
gtk::DialogFlags::empty(),
style,
button_style,
text,
);
let result = dialog.run();
unsafe {
dialog.destroy();
}
result
}
#[cfg(windows)]
fn match_response_type(result: Result) -> ResponseType {
use windows_sys::Win32::UI::WindowsAndMessaging::*;
match result {
IDOK => ResponseType::Ok,
IDYES => ResponseType::Yes,
IDNO => ResponseType::No,
IDCANCEL => ResponseType::Cancel,
IDCLOSE => ResponseType::Close,
_ => ResponseType::None,
}
}
#[cfg(unix)]
fn match_response_type(result: Result) -> ResponseType {
match result {
gtk::ResponseType::Ok => ResponseType::Ok,
gtk::ResponseType::Yes => ResponseType::Yes,
gtk::ResponseType::No => ResponseType::No,
gtk::ResponseType::Cancel => ResponseType::Cancel,
gtk::ResponseType::Close => ResponseType::Close,
_ => ResponseType::None,
}
}
pub fn show_dialog(text: &str, caption: &str) -> ResponseType {
let result = MsgBox::show_base_dialog(text, caption, MS_NONE, BS_OK);
MsgBox::match_response_type(result)
}
pub fn show_information_dialog(text: &str, caption: &str) -> ResponseType {
let result = MsgBox::show_base_dialog(text, caption, MS_INFORMATION, BS_OK);
MsgBox::match_response_type(result)
}
pub fn show_question_dialog(text: &str, caption: &str) -> ResponseType {
let result = MsgBox::show_base_dialog(text, caption, MS_QUESTION, BS_YESNO);
MsgBox::match_response_type(result)
}
pub fn show_warning_dialog(text: &str, caption: &str) -> ResponseType {
let result = MsgBox::show_base_dialog(text, caption, MS_WARNING, BS_OK);
MsgBox::match_response_type(result)
}
pub fn show_error_dialog(text: &str, caption: &str) -> ResponseType {
let result = MsgBox::show_base_dialog(text, caption, MS_ERROR, BS_OK);
MsgBox::match_response_type(result)
}
}