use crate::gpu;
#[cfg(all(target_os = "android", feature = "android"))]
mod android;
#[cfg(target_os = "ios")]
mod ios;
#[cfg_attr(not(all(target_os = "android", feature = "android")), allow(dead_code))]
mod text_input;
#[cfg(all(target_os = "android", feature = "android"))]
pub use android::{AndroidApp, run_android};
pub type InstallFonts = Box<dyn FnOnce(&egui::Context)>;
pub struct WindowOptions {
title: String,
inner_size: [f32; 2],
min_inner_size: [f32; 2],
fonts: Option<InstallFonts>,
#[cfg(feature = "serde")]
store: Option<crate::store::Store>,
}
impl WindowOptions {
pub fn new(title: impl Into<String>) -> WindowOptions {
WindowOptions {
title: title.into(),
inner_size: [900.0, 600.0],
min_inner_size: [600.0, 400.0],
fonts: None,
#[cfg(feature = "serde")]
store: None,
}
}
pub fn inner_size(mut self, size: [f32; 2]) -> WindowOptions {
self.inner_size = size;
self
}
pub fn min_inner_size(mut self, size: [f32; 2]) -> WindowOptions {
self.min_inner_size = size;
self
}
pub fn fonts(mut self, install: impl FnOnce(&egui::Context) + 'static) -> WindowOptions {
self.fonts = Some(Box::new(install));
self
}
#[cfg(feature = "serde")]
pub fn remember(mut self, store: crate::store::Store) -> WindowOptions {
self.store = Some(store);
self
}
#[cfg_attr(not(feature = "serde"), allow(unused_mut))]
pub(crate) fn wrap_create<'f>(
&mut self,
create: impl FnOnce(&eframe::CreationContext<'_>) -> Box<dyn eframe::App> + 'f,
) -> impl FnOnce(&eframe::CreationContext<'_>) -> Box<dyn eframe::App> + 'f {
#[cfg(feature = "serde")]
let store = self.store.take();
move |cc| {
#[cfg(feature = "serde")]
if let Some(store) = store {
crate::store::attach(&cc.egui_ctx, store);
}
create(cc)
}
}
}
pub fn run(
options: WindowOptions,
create: impl FnOnce(&eframe::CreationContext<'_>) -> Box<dyn eframe::App>,
) -> eframe::Result<()> {
let mut options = options;
let create = options.wrap_create(create);
let WindowOptions {
title,
inner_size,
min_inner_size,
fonts,
..
} = options;
gpu::install_panic_hook();
let native = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_inner_size(inner_size)
.with_min_inner_size(min_inner_size)
.with_title(&title),
wgpu_options: gpu::wgpu_options(),
..Default::default()
};
open(&title, native, fonts, create)
}
pub fn open(
title: &str,
native: eframe::NativeOptions,
fonts: Option<InstallFonts>,
create: impl FnOnce(&eframe::CreationContext<'_>) -> Box<dyn eframe::App>,
) -> eframe::Result<()> {
eframe::run_native(
title,
native,
Box::new(move |cc| {
gpu::on_render_state(cc.wgpu_render_state.as_ref());
match fonts {
Some(install) => install(&cc.egui_ctx),
None => {
crate::fonts::install_system_cjk_fallback(&cc.egui_ctx);
}
}
let app = create(cc);
#[cfg(target_os = "ios")]
let app = ios::full_screen(cc, app);
Ok(app)
}),
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn options_default_and_override_the_window_size() {
let options = WindowOptions::new("Example");
assert_eq!(options.title, "Example");
assert_eq!(options.inner_size, [900.0, 600.0]);
assert_eq!(options.min_inner_size, [600.0, 400.0]);
assert!(options.fonts.is_none());
let options = options
.inner_size([1000.0, 640.0])
.min_inner_size([720.0, 440.0])
.fonts(|_| {});
assert_eq!(options.inner_size, [1000.0, 640.0]);
assert_eq!(options.min_inner_size, [720.0, 440.0]);
assert!(options.fonts.is_some());
}
}