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