Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eframe web: access app from WebHandle #1886

Merged
merged 6 commits into from
Sep 9, 2022
Merged

Conversation

enomado
Copy link
Contributor

@enomado enomado commented Aug 3, 2022

This is a way to communicate with ConcreteApp from JavaScript.

There are few ways how to do it -

  1. place ConcreteApp in a Arc 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
Copy link
Contributor Author

enomado commented Aug 3, 2022

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?

eframe/src/epi.rs Outdated Show resolved Hide resolved
egui_demo_app/src/lib.rs Outdated Show resolved Hide resolved
@emilk
Copy link
Owner

emilk commented Aug 4, 2022

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.

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
@emilk emilk changed the title handle for app from WehHandle handle for app from WebHandle Aug 10, 2022
@emilk
Copy link
Owner

emilk commented Aug 20, 2022

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;
     }
 }

@enomado
Copy link
Contributor Author

enomado commented Sep 8, 2022

How to merge this now...

@enomado
Copy link
Contributor Author

enomado commented Sep 8, 2022

Can we merge this now?

@enomado
Copy link
Contributor Author

enomado commented Sep 8, 2022

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...

@emilk
Copy link
Owner

emilk commented Sep 8, 2022

Can you please apply my diff first?

@enomado
Copy link
Contributor Author

enomado commented Sep 8, 2022

done

@emilk emilk changed the title handle for app from WebHandle eframe web: access app from WebHandle Sep 9, 2022
@emilk emilk merged commit ebc4fc8 into emilk:master Sep 9, 2022
@emilk
Copy link
Owner

emilk commented Sep 9, 2022

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants