[egui_web] Repaint on finished fetch in example app
This commit is contained in:
parent
99a2a52510
commit
633b19ee99
8 changed files with 129 additions and 71 deletions
2
TODO.md
2
TODO.md
|
@ -62,8 +62,8 @@ TODO-list for the Egui project. If you looking for something to do, look here.
|
|||
* [x] Read url fragment and redirect to a subpage (e.g. different examples apps)]
|
||||
* [x] Copy/paste support
|
||||
* [x] Async HTTP requests
|
||||
* [x] Repaint on completed fetch request (etc)
|
||||
* [ ] Local storage of app state
|
||||
* [ ] Repaint on completed fetch request (etc)
|
||||
* [ ] Fix WebGL colors/blending (try EXT_sRGB)
|
||||
* [ ] Embeddability
|
||||
* [ ] Support canvas that does NOT cover entire screen.
|
||||
|
|
|
@ -213,35 +213,35 @@ function makeMutClosure(arg0, arg1, dtor, f) {
|
|||
return real;
|
||||
}
|
||||
function __wbg_adapter_26(arg0, arg1) {
|
||||
wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hcf118a068d67b888(arg0, arg1);
|
||||
wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h131d7a2b30673af8(arg0, arg1);
|
||||
}
|
||||
|
||||
function __wbg_adapter_29(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h232550930f57d037(arg0, arg1, addHeapObject(arg2));
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h1fcff379f8a91500(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function __wbg_adapter_32(arg0, arg1) {
|
||||
wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__ha5199f647b73bd92(arg0, arg1);
|
||||
function __wbg_adapter_32(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h1fcff379f8a91500(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function __wbg_adapter_35(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h232550930f57d037(arg0, arg1, addHeapObject(arg2));
|
||||
function __wbg_adapter_35(arg0, arg1) {
|
||||
wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h41cd408ae7dd46f7(arg0, arg1);
|
||||
}
|
||||
|
||||
function __wbg_adapter_38(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h232550930f57d037(arg0, arg1, addHeapObject(arg2));
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h1fcff379f8a91500(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function __wbg_adapter_41(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h232550930f57d037(arg0, arg1, addHeapObject(arg2));
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h1fcff379f8a91500(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function __wbg_adapter_44(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h232550930f57d037(arg0, arg1, addHeapObject(arg2));
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h1fcff379f8a91500(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function __wbg_adapter_47(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hd5c13e870f8bfcb3(arg0, arg1, addHeapObject(arg2));
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h42bc6cd1f6265a35(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -381,10 +381,6 @@ async function init(input) {
|
|||
var ret = getObject(arg0).fetch(getObject(arg1));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_setInterval_06df6f1ebeafd66f = handleError(function(arg0, arg1, arg2) {
|
||||
var ret = getObject(arg0).setInterval(getObject(arg1), arg2);
|
||||
return ret;
|
||||
});
|
||||
imports.wbg.__wbg_body_8c888fe47d81765f = function(arg0) {
|
||||
var ret = getObject(arg0).body;
|
||||
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
||||
|
@ -870,36 +866,36 @@ async function init(input) {
|
|||
var ret = wasm.memory;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper738 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 211, __wbg_adapter_26);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper739 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 211, __wbg_adapter_29);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper741 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 211, __wbg_adapter_32);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper743 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 211, __wbg_adapter_35);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper745 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 211, __wbg_adapter_38);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper748 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 211, __wbg_adapter_41);
|
||||
var ret = makeMutClosure(arg0, arg1, 214, __wbg_adapter_26);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper750 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 211, __wbg_adapter_44);
|
||||
imports.wbg.__wbindgen_closure_wrapper749 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 214, __wbg_adapter_29);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper1475 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 242, __wbg_adapter_47);
|
||||
imports.wbg.__wbindgen_closure_wrapper751 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 214, __wbg_adapter_32);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper753 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 214, __wbg_adapter_35);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper755 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 214, __wbg_adapter_38);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper758 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 214, __wbg_adapter_41);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper760 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 214, __wbg_adapter_44);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper1496 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 252, __wbg_adapter_47);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
|
||||
|
|
Binary file not shown.
|
@ -36,6 +36,8 @@ pub struct IntegrationContext<'a> {
|
|||
pub tex_allocator: Option<&'a mut dyn TextureAllocator>,
|
||||
/// Where the app can issue commands back to the integration.
|
||||
pub output: AppOutput,
|
||||
/// If you need to request a repaint from another thread, clone this and give to that other thread
|
||||
pub repaint_signal: std::sync::Arc<dyn RepaintSignal>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -92,6 +94,12 @@ pub trait TextureAllocator {
|
|||
fn free(&mut self, id: crate::TextureId);
|
||||
}
|
||||
|
||||
pub trait RepaintSignal: Send {
|
||||
/// This signals the Egui integration that a repaint is required.
|
||||
/// This is meant to be called when a background process finishes in an async context and/or background thread.
|
||||
fn request_repaint(&self);
|
||||
}
|
||||
|
||||
/// A place where you can store custom data in a way that persists when you restart the app.
|
||||
///
|
||||
/// On the web this is backed by [local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
|
||||
|
|
|
@ -29,10 +29,20 @@ impl egui::app::TextureAllocator for Painter {
|
|||
}
|
||||
}
|
||||
|
||||
struct RequestRepaintEvent;
|
||||
|
||||
struct GliumRepaintSignal(glutin::event_loop::EventLoopProxy<RequestRepaintEvent>);
|
||||
|
||||
impl egui::app::RepaintSignal for GliumRepaintSignal {
|
||||
fn request_repaint(&self) {
|
||||
self.0.send_event(RequestRepaintEvent).ok();
|
||||
}
|
||||
}
|
||||
|
||||
fn create_display(
|
||||
title: &str,
|
||||
window_settings: Option<WindowSettings>,
|
||||
event_loop: &glutin::event_loop::EventLoop<()>,
|
||||
event_loop: &glutin::event_loop::EventLoop<RequestRepaintEvent>,
|
||||
) -> glium::Display {
|
||||
let mut window_builder = glutin::window::WindowBuilder::new()
|
||||
.with_decorations(true)
|
||||
|
@ -61,9 +71,11 @@ pub fn run(
|
|||
) -> ! {
|
||||
let window_settings: Option<WindowSettings> =
|
||||
egui::app::get_value(storage.as_ref(), WINDOW_KEY);
|
||||
let event_loop = glutin::event_loop::EventLoop::new();
|
||||
let event_loop = glutin::event_loop::EventLoop::with_user_event();
|
||||
let display = create_display(title, window_settings, &event_loop);
|
||||
|
||||
let repaint_signal = std::sync::Arc::new(GliumRepaintSignal(event_loop.create_proxy()));
|
||||
|
||||
let mut ctx = egui::Context::new();
|
||||
*ctx.memory() = egui::app::get_value(storage.as_ref(), EGUI_MEMORY_KEY).unwrap_or_default();
|
||||
app.setup(&ctx);
|
||||
|
@ -92,6 +104,7 @@ pub fn run(
|
|||
},
|
||||
tex_allocator: Some(&mut painter),
|
||||
output: Default::default(),
|
||||
repaint_signal: repaint_signal.clone(),
|
||||
};
|
||||
app.ui(&ctx, &mut integration_context);
|
||||
let app_output = integration_context.output;
|
||||
|
@ -158,6 +171,11 @@ pub fn run(
|
|||
app.on_exit(storage.as_mut());
|
||||
storage.flush();
|
||||
}
|
||||
|
||||
glutin::event::Event::UserEvent(RequestRepaintEvent) => {
|
||||
display.gl_window().window().request_redraw();
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
|
|
|
@ -134,12 +134,40 @@ impl WebInput {
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
|
||||
pub struct NeedRepaint(std::sync::atomic::AtomicBool);
|
||||
|
||||
impl Default for NeedRepaint {
|
||||
fn default() -> Self {
|
||||
Self(true.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl NeedRepaint {
|
||||
pub fn fetch_and_clear(&self) -> bool {
|
||||
self.0.swap(false, SeqCst)
|
||||
}
|
||||
|
||||
pub fn set_true(&self) {
|
||||
self.0.store(true, SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
impl egui::app::RepaintSignal for NeedRepaint {
|
||||
fn request_repaint(&self) {
|
||||
self.0.store(true, SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
pub struct AppRunner {
|
||||
pixels_per_point: f32,
|
||||
pub web_backend: WebBackend,
|
||||
pub input: WebInput,
|
||||
pub app: Box<dyn App>,
|
||||
pub needs_repaint: bool, // TODO: move
|
||||
pub needs_repaint: std::sync::Arc<NeedRepaint>,
|
||||
}
|
||||
|
||||
impl AppRunner {
|
||||
|
@ -150,7 +178,7 @@ impl AppRunner {
|
|||
web_backend,
|
||||
input: Default::default(),
|
||||
app,
|
||||
needs_repaint: true, // TODO: move
|
||||
needs_repaint: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -175,6 +203,7 @@ impl AppRunner {
|
|||
},
|
||||
tex_allocator: Some(&mut self.web_backend.painter),
|
||||
output: Default::default(),
|
||||
repaint_signal: self.needs_repaint.clone(),
|
||||
};
|
||||
|
||||
let egui_ctx = &self.web_backend.ctx;
|
||||
|
|
|
@ -15,18 +15,22 @@ use wasm_bindgen::prelude::*;
|
|||
// ----------------------------------------------------------------------------
|
||||
// Helpers to hide some of the verbosity of web_sys
|
||||
|
||||
/// Log some text to the developer console (`console.log(...)` in JS)
|
||||
pub fn console_log(s: impl Into<JsValue>) {
|
||||
web_sys::console::log_1(&s.into());
|
||||
}
|
||||
|
||||
/// Log a warning to the developer console (`console.warn(...)` in JS)
|
||||
pub fn console_warn(s: impl Into<JsValue>) {
|
||||
web_sys::console::warn_1(&s.into());
|
||||
}
|
||||
|
||||
/// Log an error to the developer console (`console.error(...)` in JS)
|
||||
pub fn console_error(s: impl Into<JsValue>) {
|
||||
web_sys::console::error_1(&s.into());
|
||||
}
|
||||
|
||||
/// Current time in seconds (since undefined point in time)
|
||||
pub fn now_sec() -> f64 {
|
||||
web_sys::window()
|
||||
.expect("should have a Window")
|
||||
|
@ -298,11 +302,12 @@ pub struct AppRunnerRef(Arc<Mutex<AppRunner>>);
|
|||
fn paint_and_schedule(runner_ref: AppRunnerRef) -> Result<(), JsValue> {
|
||||
fn paint_if_needed(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
||||
let mut runner_lock = runner_ref.0.lock();
|
||||
if runner_lock.needs_repaint {
|
||||
runner_lock.needs_repaint = false;
|
||||
if runner_lock.needs_repaint.fetch_and_clear() {
|
||||
let (output, paint_jobs) = runner_lock.logic()?;
|
||||
runner_lock.paint(paint_jobs)?;
|
||||
runner_lock.needs_repaint |= output.needs_repaint;
|
||||
if output.needs_repaint {
|
||||
runner_lock.needs_repaint.set_true();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -350,7 +355,7 @@ fn install_document_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
if !modifiers.ctrl && !modifiers.command && !should_ignore_key(&key) {
|
||||
runner_lock.input.raw.events.push(egui::Event::Text(key));
|
||||
}
|
||||
runner_lock.needs_repaint = true;
|
||||
runner_lock.needs_repaint.set_true();
|
||||
|
||||
// So, shall we call prevent_default?
|
||||
// YES:
|
||||
|
@ -392,7 +397,7 @@ fn install_document_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
modifiers,
|
||||
});
|
||||
}
|
||||
runner_lock.needs_repaint = true;
|
||||
runner_lock.needs_repaint.set_true();
|
||||
}) as Box<dyn FnMut(_)>);
|
||||
document.add_event_listener_with_callback("keyup", closure.as_ref().unchecked_ref())?;
|
||||
closure.forget();
|
||||
|
@ -406,7 +411,7 @@ fn install_document_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
if let Ok(text) = data.get_data("text") {
|
||||
let mut runner_lock = runner_ref.0.lock();
|
||||
runner_lock.input.raw.events.push(egui::Event::Text(text));
|
||||
runner_lock.needs_repaint = true;
|
||||
runner_lock.needs_repaint.set_true();
|
||||
}
|
||||
}
|
||||
}) as Box<dyn FnMut(_)>);
|
||||
|
@ -420,7 +425,7 @@ fn install_document_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
let closure = Closure::wrap(Box::new(move |_: web_sys::ClipboardEvent| {
|
||||
let mut runner_lock = runner_ref.0.lock();
|
||||
runner_lock.input.raw.events.push(egui::Event::Cut);
|
||||
runner_lock.needs_repaint = true;
|
||||
runner_lock.needs_repaint.set_true();
|
||||
}) as Box<dyn FnMut(_)>);
|
||||
document.add_event_listener_with_callback("cut", closure.as_ref().unchecked_ref())?;
|
||||
closure.forget();
|
||||
|
@ -432,7 +437,7 @@ fn install_document_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
let closure = Closure::wrap(Box::new(move |_: web_sys::ClipboardEvent| {
|
||||
let mut runner_lock = runner_ref.0.lock();
|
||||
runner_lock.input.raw.events.push(egui::Event::Copy);
|
||||
runner_lock.needs_repaint = true;
|
||||
runner_lock.needs_repaint.set_true();
|
||||
}) as Box<dyn FnMut(_)>);
|
||||
document.add_event_listener_with_callback("copy", closure.as_ref().unchecked_ref())?;
|
||||
closure.forget();
|
||||
|
@ -441,7 +446,7 @@ fn install_document_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
for event_name in &["load", "pagehide", "pageshow", "resize"] {
|
||||
let runner_ref = runner_ref.clone();
|
||||
let closure = Closure::wrap(Box::new(move || {
|
||||
runner_ref.0.lock().needs_repaint = true;
|
||||
runner_ref.0.lock().needs_repaint.set_true();
|
||||
}) as Box<dyn FnMut()>);
|
||||
window.add_event_listener_with_callback(event_name, closure.as_ref().unchecked_ref())?;
|
||||
closure.forget();
|
||||
|
@ -457,7 +462,7 @@ fn repaint_every_ms(runner_ref: &AppRunnerRef, milliseconds: i32) -> Result<(),
|
|||
let window = web_sys::window().unwrap();
|
||||
let runner_ref = runner_ref.clone();
|
||||
let closure = Closure::wrap(Box::new(move || {
|
||||
runner_ref.0.lock().needs_repaint = true;
|
||||
runner_ref.0.lock().needs_repaint.set_true();
|
||||
}) as Box<dyn FnMut()>);
|
||||
window.set_interval_with_callback_and_timeout_and_arguments_0(
|
||||
closure.as_ref().unchecked_ref(),
|
||||
|
@ -497,7 +502,7 @@ fn install_canvas_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
Some(pos_from_mouse_event(runner_lock.canvas_id(), &event));
|
||||
runner_lock.input.raw.mouse_down = true;
|
||||
runner_lock.logic().unwrap(); // in case we get "mouseup" the same frame. TODO: handle via events instead
|
||||
runner_lock.needs_repaint = true;
|
||||
runner_lock.needs_repaint.set_true();
|
||||
event.stop_propagation();
|
||||
event.prevent_default();
|
||||
}
|
||||
|
@ -514,7 +519,7 @@ fn install_canvas_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
if !runner_lock.input.is_touch {
|
||||
runner_lock.input.mouse_pos =
|
||||
Some(pos_from_mouse_event(runner_lock.canvas_id(), &event));
|
||||
runner_lock.needs_repaint = true;
|
||||
runner_lock.needs_repaint.set_true();
|
||||
event.stop_propagation();
|
||||
event.prevent_default();
|
||||
}
|
||||
|
@ -532,7 +537,7 @@ fn install_canvas_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
runner_lock.input.mouse_pos =
|
||||
Some(pos_from_mouse_event(runner_lock.canvas_id(), &event));
|
||||
runner_lock.input.raw.mouse_down = false;
|
||||
runner_lock.needs_repaint = true;
|
||||
runner_lock.needs_repaint.set_true();
|
||||
event.stop_propagation();
|
||||
event.prevent_default();
|
||||
}
|
||||
|
@ -548,7 +553,7 @@ fn install_canvas_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
let mut runner_lock = runner_ref.0.lock();
|
||||
if !runner_lock.input.is_touch {
|
||||
runner_lock.input.mouse_pos = None;
|
||||
runner_lock.needs_repaint = true;
|
||||
runner_lock.needs_repaint.set_true();
|
||||
event.stop_propagation();
|
||||
event.prevent_default();
|
||||
}
|
||||
|
@ -565,7 +570,7 @@ fn install_canvas_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
runner_lock.input.is_touch = true;
|
||||
runner_lock.input.mouse_pos = Some(pos_from_touch_event(&event));
|
||||
runner_lock.input.raw.mouse_down = true;
|
||||
runner_lock.needs_repaint = true;
|
||||
runner_lock.needs_repaint.set_true();
|
||||
event.stop_propagation();
|
||||
event.prevent_default();
|
||||
}) as Box<dyn FnMut(_)>);
|
||||
|
@ -580,7 +585,7 @@ fn install_canvas_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
let mut runner_lock = runner_ref.0.lock();
|
||||
runner_lock.input.is_touch = true;
|
||||
runner_lock.input.mouse_pos = Some(pos_from_touch_event(&event));
|
||||
runner_lock.needs_repaint = true;
|
||||
runner_lock.needs_repaint.set_true();
|
||||
event.stop_propagation();
|
||||
event.prevent_default();
|
||||
}) as Box<dyn FnMut(_)>);
|
||||
|
@ -597,7 +602,7 @@ fn install_canvas_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
runner_lock.input.raw.mouse_down = false; // First release mouse to click...
|
||||
runner_lock.logic().unwrap(); // ...do the clicking... (TODO: handle via events instead)
|
||||
runner_lock.input.mouse_pos = None; // ...remove hover effect
|
||||
runner_lock.needs_repaint = true;
|
||||
runner_lock.needs_repaint.set_true();
|
||||
event.stop_propagation();
|
||||
event.prevent_default();
|
||||
}) as Box<dyn FnMut(_)>);
|
||||
|
@ -612,7 +617,7 @@ fn install_canvas_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
|
|||
let mut runner_lock = runner_ref.0.lock();
|
||||
runner_lock.input.scroll_delta.x -= event.delta_x() as f32;
|
||||
runner_lock.input.scroll_delta.y -= event.delta_y() as f32;
|
||||
runner_lock.needs_repaint = true;
|
||||
runner_lock.needs_repaint.set_true();
|
||||
event.stop_propagation();
|
||||
event.prevent_default();
|
||||
}) as Box<dyn FnMut(_)>);
|
||||
|
|
|
@ -46,6 +46,15 @@ impl egui::app::App for ExampleApp {
|
|||
ctx: &std::sync::Arc<egui::Context>,
|
||||
integration_context: &mut egui::app::IntegrationContext,
|
||||
) {
|
||||
if let Some(receiver) = &mut self.in_progress {
|
||||
// Are we there yet?
|
||||
if let Ok(result) = receiver.try_recv() {
|
||||
self.in_progress = None;
|
||||
self.result = Some(result.map(Resource::from_response));
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.heading("Egui Example App");
|
||||
ui.add(egui::github_link_file!(
|
||||
|
@ -54,12 +63,13 @@ impl egui::app::App for ExampleApp {
|
|||
));
|
||||
|
||||
if ui_url(ui, &mut self.url) {
|
||||
let repaint_signal = integration_context.repaint_signal.clone();
|
||||
let (sender, receiver) = std::sync::mpsc::channel();
|
||||
self.in_progress = Some(receiver);
|
||||
let url = self.url.clone();
|
||||
egui_web::spawn_future(async move {
|
||||
sender.send(egui_web::fetch::get(&url).await).ok();
|
||||
// TODO: trigger egui repaint somehow
|
||||
repaint_signal.request_repaint();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -79,14 +89,6 @@ impl egui::app::App for ExampleApp {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(receiver) = &mut self.in_progress {
|
||||
// Are we there yet?
|
||||
if let Ok(result) = receiver.try_recv() {
|
||||
self.in_progress = None;
|
||||
self.result = Some(result.map(Resource::from_response));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue