use std::marker::PhantomData;
use std::sync::Mutex;
use crate::ui::common::traits::Control;
use crate::ui::common::traits::NotModalWindow;
use crate::ui::common::traits::WindowControl;
use super::Error;
use super::ErrorKind;
use super::RuntimeManager;
use super::Theme;
use super::ThemeMethods;
static APP_CREATED_MUTEX: Mutex<bool> = Mutex::new(false);
#[cfg(target_arch = "wasm32")]
const WEBTERMINAL_END_MESSAGE_HTML: &str = "<h1>{} has ended</h1><p>To re-start the application, please refresh the page.</p>";
pub struct App {
_phantom: PhantomData<*mut ()>,
}
impl App {
pub(super) fn is_created() -> bool {
let app_created = APP_CREATED_MUTEX.lock().unwrap();
*app_created
}
pub(super) fn create(builder: crate::system::InternalBuilder) -> Result<Self, Error> {
if APP_CREATED_MUTEX.is_poisoned() {
APP_CREATED_MUTEX.clear_poison();
}
let mut app_created = APP_CREATED_MUTEX.lock().unwrap();
if *app_created {
return Err(Error::new(
ErrorKind::InitializationFailure,
"App has already been created ! There can only be one instance of an Application at one time. If you have more, make sure that you have only one !".to_string(),
));
}
RuntimeManager::create(builder)?;
*app_created = true;
Ok(App {
_phantom: Default::default(),
})
}
#[allow(clippy::new_ret_no_self)]
pub fn new() -> crate::system::MultiWindowAppBuilder {
crate::system::MultiWindowAppBuilder::new()
}
#[allow(clippy::new_ret_no_self)]
pub fn single_window<F, T>(factory: F) -> crate::system::SingleWindowAppBuilder
where
F: FnOnce() -> T + 'static,
T: Control + WindowControl + NotModalWindow + 'static,
{
crate::system::SingleWindowAppBuilder::new(factory)
}
#[allow(clippy::new_ret_no_self)]
pub fn frame_app<T: crate::system::FrameApp + 'static>(frame_app: T) -> crate::system::FrameAppBuilder<T> {
crate::system::FrameAppBuilder::new(frame_app)
}
#[allow(clippy::new_ret_no_self)]
pub fn input_app<T: crate::system::InputApp + 'static>(input_app: T) -> crate::system::InputAppBuilder<T> {
crate::system::InputAppBuilder::new(input_app)
}
pub(crate) fn start_app(self) -> Result<(), crate::system::Error> {
#[cfg(target_arch = "wasm32")]
#[allow(unused_imports)]
{
use wasm_bindgen_rayon::init_thread_pool; console_error_panic_hook::set_once();
}
RuntimeManager::get().run();
RuntimeManager::get().backend_mut().on_close();
crate::dialogs::clear_last_path();
#[cfg(not(target_arch = "wasm32"))]
{
RuntimeManager::destroy();
let mut app_created = APP_CREATED_MUTEX.lock().unwrap();
*app_created = false;
}
Ok(())
}
pub fn set_theme(theme: Theme) {
if !App::is_created() {
panic!("App::set_theme can only be called after the App has been created !");
}
RuntimeManager::get().set_theme(theme);
}
pub fn close() {
if App::is_created() {
RuntimeManager::get().close();
}
}
pub(crate) fn drop_app() {
if APP_CREATED_MUTEX.is_poisoned() {
APP_CREATED_MUTEX.clear_poison();
}
if RuntimeManager::is_instantiated() {
RuntimeManager::destroy();
}
let mut app_created = APP_CREATED_MUTEX.lock().unwrap();
*app_created = false;
#[cfg(target_arch = "wasm32")]
{
use web_sys::window;
if let Some(win) = window() {
if let Some(doc) = win.document() {
if let Some(body) = doc.body() {
body.set_inner_html(&WEBTERMINAL_END_MESSAGE_HTML.replace("{}", &doc.title()));
}
}
}
}
}
}
#[cfg(not(target_arch = "wasm32"))]
impl Drop for App {
fn drop(&mut self) {
Self::drop_app();
}
}