#![allow(missing_copy_implementations)]
use core::ffi::c_void;
use azul_core::window::AzStringPair;
use azul_css::{impl_option, impl_option_inner, props::basic::color::ColorU, AzString, StringVec};
use tfd::{DefaultColorValue, MessageBoxIcon};
#[derive(Debug)]
pub struct MsgBox {
pub _reserved: *mut c_void,
}
#[derive(Debug)]
pub struct FileDialog {
pub _reserved: *mut c_void,
}
#[derive(Debug)]
pub struct ColorPickerDialog {
pub _reserved: *mut c_void,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum OkCancel {
Ok,
Cancel,
}
impl From<tfd::OkCancel> for OkCancel {
#[inline]
fn from(e: tfd::OkCancel) -> Self {
match e {
tfd::OkCancel::Ok => OkCancel::Ok,
tfd::OkCancel::Cancel => OkCancel::Cancel,
}
}
}
impl From<OkCancel> for tfd::OkCancel {
#[inline]
fn from(e: OkCancel) -> Self {
match e {
OkCancel::Ok => tfd::OkCancel::Ok,
OkCancel::Cancel => tfd::OkCancel::Cancel,
}
}
}
pub fn msg_box_ok_cancel(
title: &str,
message: &str,
icon: MessageBoxIcon,
default: OkCancel,
) -> OkCancel {
let msg_box = tfd::MessageBox::new(title, message)
.with_icon(icon)
.run_modal_ok_cancel(default.into());
msg_box.into()
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[repr(C)]
pub enum YesNo {
Yes,
No,
}
impl From<YesNo> for tfd::YesNo {
#[inline]
fn from(e: YesNo) -> Self {
match e {
YesNo::Yes => tfd::YesNo::Yes,
YesNo::No => tfd::YesNo::No,
}
}
}
impl From<tfd::YesNo> for YesNo {
#[inline]
fn from(e: tfd::YesNo) -> Self {
match e {
tfd::YesNo::Yes => YesNo::Yes,
tfd::YesNo::No => YesNo::No,
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[repr(C)]
pub enum MsgBoxIcon {
Info,
Warning,
Error,
Question,
}
impl From<MsgBoxIcon> for MessageBoxIcon {
#[inline]
fn from(e: MsgBoxIcon) -> Self {
match e {
MsgBoxIcon::Info => MessageBoxIcon::Info,
MsgBoxIcon::Warning => MessageBoxIcon::Warning,
MsgBoxIcon::Error => MessageBoxIcon::Error,
MsgBoxIcon::Question => MessageBoxIcon::Question,
}
}
}
pub fn msg_box_yes_no(title: &str, message: &str, icon: MessageBoxIcon, default: YesNo) -> YesNo {
let msg_box = tfd::MessageBox::new(title, message)
.with_icon(icon)
.run_modal_yes_no(default.into());
msg_box.into()
}
pub fn msg_box_ok(title: &str, message: &str, icon: MessageBoxIcon) {
let mut msg = message.to_string();
msg = msg.replace('\"', "");
msg = msg.replace('\'', "");
tfd::MessageBox::new(title, &msg)
.with_icon(icon)
.run_modal();
}
pub fn msg_box(content: &str) {
msg_box_ok("Info", content, MessageBoxIcon::Info);
}
pub fn color_picker_dialog(title: &str, default_value: Option<ColorU>) -> Option<ColorU> {
let rgb = default_value.map_or([0, 0, 0], |c| [c.r, c.g, c.b]);
let default_color = DefaultColorValue::RGB(rgb);
let result = tfd::ColorChooser::new(title)
.with_default_color(default_color)
.run_modal()?;
Some(ColorU {
r: result.1[0],
g: result.1[1],
b: result.1[2],
a: ColorU::ALPHA_OPAQUE,
})
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct FileTypeList {
pub document_types: StringVec,
pub document_descriptor: AzString,
}
impl_option!(
FileTypeList,
OptionFileTypeList,
copy = false,
[Debug, Clone, PartialEq, PartialOrd]
);
pub fn open_file_dialog(
title: &str,
default_path: Option<&str>,
filter_list: Option<FileTypeList>,
) -> Option<AzString> {
let mut dialog = tfd::FileDialog::new(title);
if let Some(path) = default_path {
dialog = dialog.with_path(path);
}
if let Some(filter) = filter_list {
let v = filter.document_types.clone().into_library_owned_vec();
let patterns: Vec<&str> = v.iter().map(|s| s.as_str()).collect();
dialog = dialog.with_filter(&patterns, filter.document_descriptor.as_str());
}
dialog.open_file().map(|s| s.into())
}
pub fn open_directory_dialog(title: &str, default_path: Option<&str>) -> Option<AzString> {
let mut dialog = tfd::FileDialog::new(title);
if let Some(path) = default_path {
dialog = dialog.with_path(path);
}
dialog.select_folder().map(|s| s.into())
}
pub fn open_multiple_files_dialog(
title: &str,
default_path: Option<&str>,
filter_list: Option<FileTypeList>,
) -> Option<StringVec> {
let mut dialog = tfd::FileDialog::new(title).with_multiple_selection(true);
if let Some(path) = default_path {
dialog = dialog.with_path(path);
}
if let Some(filter) = filter_list {
let v = filter.document_types.clone().into_library_owned_vec();
let patterns: Vec<&str> = v.iter().map(|s| s.as_str()).collect();
dialog = dialog.with_filter(&patterns, filter.document_descriptor.as_str());
}
dialog.open_files().map(|s| s.into())
}
pub fn save_file_dialog(title: &str, default_path: Option<&str>) -> Option<AzString> {
let mut dialog = tfd::FileDialog::new(title);
if let Some(path) = default_path {
dialog = dialog.with_path(path);
}
dialog.save_file().map(|s| s.into())
}