egui icon indicating copy to clipboard operation
egui copied to clipboard

handle for app from WehHandle

Open enomado opened this issue 3 years ago • 2 comments

This is a way to communicate with ConcreteApp from JavaScript.

There are few ways how to do it -

  1. place ConcreteApp in a Arc<Mutex> and save it somewhere before it goes to AppRunner, so it must be not Box.
  2. make shared data in app and do nothing
  3. This way. Its actually elegant and not quite hacky.

I tried to cast Box<dyn App> to &dyn Any other ways, and dont find a solution.

I stuck with `static lifetime, or this

here is the playground

enomado avatar Aug 03 '22 10:08 enomado

I'm not understand what lint wants from me

error: missing documentation for an associated function

Is there is another place where it should be documented?

enomado avatar Aug 03 '22 16:08 enomado

This is a really great feature to implement, but I wonder if we can make it more ergonomic.


Let's investigate the current approach first (3.).

Every user must add

    #[cfg(target_arch = "wasm32")]
    fn as_any_mut(&mut self) -> &mut dyn Any {
        &mut *self
    }

I guess this is fine, and not much to do about it afacit.

However, I think we can improve this part:

    fn with_app<F>(&mut self, func: F) -> ()
    where
        F: Fn(&mut ConcreteApp) -> (),
    {
        let mut runner_ref = self.handle.lock();
        let app_ref = runner_ref.get_app_mut();
        let app = app_ref.downcast_mut::<ConcreteApp>().unwrap();
        func(app);
    }

   #[wasm_bindgen]	
    pub fn set_some_content_from_javasript(&mut self, _some_data: &str) {
        self.with_app(|app| {
            app.data = some_data;
        });
    }

With a helper function, this could become:

   #[wasm_bindgen]	
    pub fn set_some_content_from_javasript(&mut self, _some_data: &str) {
        let app = self.handle.lock().app_mut::<ConcreteApp>();
        app.data = some_data;
    }

much nicer!


About option 1 (Arc). We would need something like Arc<Mutex<Box<dyn App>>> on one end and Arc<Mutex<Box<ConcreteApp>>> on the other end. Is that even possible? If it was it would save users from having to implement as_any_mut, which is pretty nice.

emilk avatar Aug 04 '22 12:08 emilk

I don't understand GitHub. I pushed one commit, and it shows up here. I push another, and it doesn't show up.

diff --git a/eframe/src/web/backend.rs b/eframe/src/web/backend.rs
index 7849ea72..f231172a 100644
--- a/eframe/src/web/backend.rs
+++ b/eframe/src/web/backend.rs
@@ -35,7 +35,7 @@ impl WebInput {
 
 // ----------------------------------------------------------------------------
 
-use std::{any::Any, sync::atomic::Ordering::SeqCst};
+use std::sync::atomic::Ordering::SeqCst;
 
 /// Stores when to do the next repaint.
 pub struct NeedRepaint(Mutex<f64>);
@@ -265,8 +265,9 @@ impl AppRunner {
         &self.egui_ctx
     }
 
-    pub fn get_app_mut(&mut self) -> &mut dyn Any {
-        self.app.as_any_mut()
+    /// Get mutable access to the concrete [`App`] we enclose.
+    pub fn app_mut<ConreteApp: 'static + crate::App>(&mut self) -> &mut ConreteApp {
+        self.app.as_any_mut().downcast_mut::<ConreteApp>().unwrap()
     }
 
     pub fn auto_save(&mut self) {
diff --git a/egui_demo_app/src/lib.rs b/egui_demo_app/src/lib.rs
index b00cad8e..aafd53ae 100644
--- a/egui_demo_app/src/lib.rs
+++ b/egui_demo_app/src/lib.rs
@@ -32,7 +32,6 @@ pub struct WebHandle {
 #[wasm_bindgen]
 impl WebHandle {
     #[wasm_bindgen]
-    #[cfg(target_arch = "wasm32")]
     pub fn stop_web(&self) -> Result<(), wasm_bindgen::JsValue> {
         let mut app = self.handle.lock();
         let res = app.destroy();
@@ -44,22 +43,10 @@ impl WebHandle {
         res
     }
 
-    // helper for mutating original app from javascript
-    fn with_app<F>(&mut self, func: F) -> ()
-    where
-        F: Fn(&mut WrapApp) -> (),
-    {
-        let mut runner_ref = self.handle.lock();
-        let app_ref = runner_ref.get_app_mut();
-        let app = app_ref.downcast_mut::<WrapApp>().unwrap();
-        func(app);
-    }
-
     #[wasm_bindgen]
     pub fn set_some_content_from_javasript(&mut self, _some_data: &str) {
-        self.with_app(|_app| {
-            // app.data = some_data;
-        });
+        let _app = self.handle.lock().app_mut::<WrapApp>();
+        // _app.data = some_data;
     }
 }

emilk avatar Aug 20 '22 08:08 emilk

How to merge this now...

enomado avatar Sep 08 '22 01:09 enomado

Can we merge this now?

enomado avatar Sep 08 '22 01:09 enomado

Hmm I dont get where is your modifications. May be we can merge this as is, since I'm only person who need this for now?

I'm so tired to manage all my outdated branches...

enomado avatar Sep 08 '22 01:09 enomado

Can you please apply my diff first?

emilk avatar Sep 08 '22 07:09 emilk

done

enomado avatar Sep 08 '22 19:09 enomado

Thanks!

emilk avatar Sep 09 '22 06:09 emilk