#![cfg_attr(docsrs, feature(doc_cfg))]
mod application;
mod convert_events;
mod event;
mod net;
mod window;
#[cfg(feature = "accessibility")]
mod accessibility;
pub use crate::application::BlitzApplication;
pub use crate::event::BlitzShellEvent;
pub use crate::net::BlitzShellNetCallback;
pub use crate::window::{View, WindowConfig};
#[cfg(feature = "data-uri")]
pub use crate::net::DataUriNetProvider;
#[cfg(all(
feature = "file_dialog",
any(
target_os = "windows",
target_os = "macos",
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
)
))]
use blitz_traits::shell::FileDialogFilter;
use blitz_traits::shell::ShellProvider;
use std::sync::Arc;
pub use winit::event_loop::{ControlFlow, EventLoop, EventLoopProxy};
pub use winit::window::{CursorIcon, Window};
#[derive(Default)]
pub struct Config {
pub stylesheets: Vec<String>,
pub base_url: Option<String>,
}
pub fn create_default_event_loop<Event>() -> EventLoop<Event> {
let mut ev_builder = EventLoop::<Event>::with_user_event();
#[cfg(target_os = "android")]
{
use winit::platform::android::EventLoopBuilderExtAndroid;
ev_builder.with_android_app(current_android_app());
}
let event_loop = ev_builder.build().unwrap();
event_loop.set_control_flow(ControlFlow::Wait);
event_loop
}
#[cfg(target_os = "android")]
static ANDROID_APP: std::sync::OnceLock<android_activity::AndroidApp> = std::sync::OnceLock::new();
#[cfg(target_os = "android")]
#[cfg_attr(docsrs, doc(cfg(target_os = "android")))]
pub fn set_android_app(app: android_activity::AndroidApp) {
ANDROID_APP.set(app).unwrap()
}
#[cfg(target_os = "android")]
#[cfg_attr(docsrs, doc(cfg(target_os = "android")))]
pub fn current_android_app() -> android_activity::AndroidApp {
ANDROID_APP.get().unwrap().clone()
}
pub struct BlitzShellProvider {
window: Arc<Window>,
}
impl BlitzShellProvider {
pub fn new(window: Arc<Window>) -> Self {
Self { window }
}
}
impl ShellProvider for BlitzShellProvider {
fn request_redraw(&self) {
self.window.request_redraw();
}
fn set_cursor(&self, icon: CursorIcon) {
self.window.set_cursor(icon);
}
fn set_window_title(&self, title: String) {
self.window.set_title(&title);
}
#[cfg(all(
feature = "clipboard",
any(
target_os = "windows",
target_os = "macos",
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
)
))]
fn get_clipboard_text(&self) -> Result<String, blitz_traits::shell::ClipboardError> {
let mut cb = arboard::Clipboard::new().unwrap();
cb.get_text()
.map_err(|_| blitz_traits::shell::ClipboardError)
}
#[cfg(all(
feature = "clipboard",
any(
target_os = "windows",
target_os = "macos",
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
)
))]
fn set_clipboard_text(&self, text: String) -> Result<(), blitz_traits::shell::ClipboardError> {
let mut cb = arboard::Clipboard::new().unwrap();
cb.set_text(text.to_owned())
.map_err(|_| blitz_traits::shell::ClipboardError)
}
#[cfg(all(
feature = "file_dialog",
any(
target_os = "windows",
target_os = "macos",
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
)
))]
fn open_file_dialog(
&self,
multiple: bool,
filter: Option<FileDialogFilter>,
) -> Vec<std::path::PathBuf> {
let mut dialog = rfd::FileDialog::new();
if let Some(FileDialogFilter { name, extensions }) = filter {
dialog = dialog.add_filter(&name, &extensions);
}
let files = if multiple {
dialog.pick_files()
} else {
dialog.pick_file().map(|file| vec![file])
};
files.unwrap_or_default()
}
}