workflow_egui/frame/
mod.rs1use crate::imports::*;
2
3pub mod options;
4pub use options::*;
5pub mod app;
6pub mod core;
7
8pub type AppCreator<T> =
9 Box<dyn FnOnce(&eframe::CreationContext<'_>, Runtime) -> std::result::Result<Box<T>, DynError>>;
10
11cfg_if! {
12 if #[cfg(not(target_arch = "wasm32"))] {
13
14 pub fn main<T,C>(options: Options<T>, events : Option<ApplicationEventsChannel>, app_creator : C)
15 where T : App,
16 C : FnOnce(&eframe::CreationContext<'_>, Runtime) -> std::result::Result<Box<T>, DynError> + 'static
17 {
18
19 #[cfg(feature = "console")] {
20 std::env::set_var("RUST_BACKTRACE", "full");
21 }
22
23 let body = async {
24 if let Err(err) = platform_main(options, events, Box::new(app_creator)).await {
25 log_error!("Error: {err}");
26 }
27 };
28
29 #[allow(clippy::expect_used, clippy::diverging_sub_expression)]
30 tokio::runtime::Builder::new_multi_thread()
31 .enable_all()
32 .build()
33 .expect("Failed building the Runtime")
34 .block_on(body);
35
36 #[cfg(feature = "console")]
37 {
38 println!("Press Enter to exit...");
39 let mut input = String::new();
40 std::io::stdin().read_line(&mut input).expect("Failed to read line");
41 }
42
43
44 }
45
46 } else {
47
48 pub fn main<T,C>(options: Options<T>, events : Option<ApplicationEventsChannel>, app_creator : C)
49 where T : App,
50 C : FnOnce(&eframe::CreationContext<'_>, Runtime) -> std::result::Result<Box<T>, DynError> + 'static
51 {
52
53 wasm_bindgen_futures::spawn_local(async {
54 log_info!("--- starting platform main... ---");
55
56 if let Err(err) = platform_main(options, events, Box::new(app_creator)).await {
58 log_error!("Error: {err}");
59 }
60 });
61
62 }
63 }
64}
65
66cfg_if! {
67 if #[cfg(not(target_arch = "wasm32"))] {
68
69 async fn platform_main<T>(options : Options<T>, events : Option<ApplicationEventsChannel>, app_creator : AppCreator<T>) -> Result<()>
70 where T : App
71 {
72 use crate::runtime::signals::Signals;
73
74 let runtime: Arc<Mutex<Option<Runtime>>> = Arc::new(Mutex::new(None));
86 let delegate = runtime.clone();
87
88 eframe::run_native(
89 options.caption.as_str(),
90 options.native_options,
91 Box::new(move |cc| {
92 let runtime = Runtime::new(&cc.egui_ctx, events);
93 delegate.lock().unwrap().replace(runtime.clone());
94 Signals::bind(&runtime);
95 runtime.start();
96
97 Ok(Box::new(core::Core::try_new(cc, runtime, app_creator)?))
98 }),
99 )?;
100
101 let runtime = runtime.lock().unwrap().take().unwrap();
102 runtime.shutdown().await;
103
104
105 Ok(())
106 }
107 } else {
108
109 async fn platform_main<T>(options : Options<T>, events : Option<ApplicationEventsChannel>, app_creator : AppCreator<T>) -> Result<()>
110 where T : App
111 {
112 use workflow_dom::utils::document;
113
114 eframe::WebLogger::init(log::LevelFilter::Debug).ok();
116
117 if let Some(element) = document().get_element_by_id("loading") {
118 element.remove();
119 }
120
121 eframe::WebRunner::new()
122 .start(
123 options.canvas_id.as_str(),
124 options.web_options,
125 Box::new(move |cc| {
126 let runtime = Runtime::new(&cc.egui_ctx, events);
127 runtime.start();
128 Ok(Box::new(core::Core::try_new(cc, runtime, app_creator)?))
129 }),
130 )
131 .await
132 .expect("failed to start eframe");
133 Ok(())
134 }
135 }
136}