vizia_core/context/
proxy.rs
1use std::any::Any;
2use std::fmt::Formatter;
3use std::sync::Mutex;
4
5use super::InternalEvent;
6
7use crate::prelude::*;
8
9pub struct ContextProxy {
14 pub current: Entity,
16 pub event_proxy: Option<Box<dyn EventProxy>>,
18}
19
20#[derive(Debug)]
22pub enum ProxyEmitError {
23 Unsupported,
25 EventLoopClosed,
27}
28
29impl std::fmt::Display for ProxyEmitError {
30 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
31 match self {
32 ProxyEmitError::Unsupported => {
33 f.write_str("The current runtime does not support proxying events")
34 }
35 ProxyEmitError::EventLoopClosed => {
36 f.write_str("Sending an event to an event loop which has been closed")
37 }
38 }
39 }
40}
41
42impl std::error::Error for ProxyEmitError {}
43
44impl ContextProxy {
45 pub fn emit<M: Any + Send>(&mut self, message: M) -> Result<(), ProxyEmitError> {
46 if let Some(proxy) = &self.event_proxy {
47 let event = Event::new(message)
48 .target(self.current)
49 .origin(self.current)
50 .propagate(Propagation::Up);
51
52 proxy.send(event).map_err(|_| ProxyEmitError::EventLoopClosed)
53 } else {
54 Err(ProxyEmitError::Unsupported)
55 }
56 }
57
58 pub fn emit_to<M: Any + Send>(
59 &mut self,
60 target: Entity,
61 message: M,
62 ) -> Result<(), ProxyEmitError> {
63 if let Some(proxy) = &self.event_proxy {
64 let event = Event::new(message)
65 .target(target)
66 .origin(self.current)
67 .propagate(Propagation::Direct);
68
69 proxy.send(event).map_err(|_| ProxyEmitError::EventLoopClosed)
70 } else {
71 Err(ProxyEmitError::Unsupported)
72 }
73 }
74
75 pub fn redraw(&mut self) -> Result<(), ProxyEmitError> {
76 self.emit(InternalEvent::Redraw)
77 }
78
79 pub fn load_image(
80 &mut self,
81 path: String,
82 data: &[u8],
83 policy: ImageRetentionPolicy,
84 ) -> Result<(), ProxyEmitError> {
85 if let Some(image) = skia_safe::Image::from_encoded(skia_safe::Data::new_copy(data)) {
86 self.emit(InternalEvent::LoadImage { path, image: Mutex::new(Some(image)), policy })?
87 }
88
89 Ok(())
90 }
91
92 pub fn spawn<F>(&self, target: F)
93 where
94 F: 'static + Send + FnOnce(&mut ContextProxy),
95 {
96 let mut cxp = self.clone();
97 std::thread::spawn(move || target(&mut cxp));
98 }
99}
100
101impl Clone for ContextProxy {
102 fn clone(&self) -> Self {
103 Self {
104 current: self.current,
105 event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
106 }
107 }
108}
109
110pub trait EventProxy: Send {
111 #[allow(clippy::result_unit_err)]
112 fn send(&self, event: Event) -> Result<(), ()>;
113 fn make_clone(&self) -> Box<dyn EventProxy>;
114}