makepad_platform/
action.rs1use crate::generate_any_trait_api;
2use crate::cx::Cx;
3use crate::thread::SignalToUI;
4use std::any::{TypeId};
5use std::fmt::Debug;
6use std::fmt;
7
8use std::sync::{
9 Mutex,
10 mpsc::{Sender}
11};
12
13
14pub (crate) static ACTION_SENDER_GLOBAL: Mutex<Option<Sender<ActionSend>>> = Mutex::new(None);
15
16pub trait ActionTrait: 'static {
17 fn debug_fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
18 fn ref_cast_type_id(&self) -> TypeId where Self: 'static {TypeId::of::<Self>()}
19}
20
21impl<T: 'static + Debug + ?Sized > ActionTrait for T {
22 fn debug_fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result{
23 self.fmt(f)
24 }
25}
26
27generate_any_trait_api!(ActionTrait);
28
29impl Debug for dyn ActionTrait {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result{
31 self.debug_fmt(f)
32 }
33}
34pub type ActionSend = Box<dyn ActionTrait + Send>;
35pub type Action = Box<dyn ActionTrait>;
36pub type ActionsBuf = Vec<Action>;
37pub type Actions = [Action];
38
39pub trait ActionDefaultRef{
40 fn default_ref()->&'static Self;
41}
42
43pub trait ActionCast<T> {
44 fn cast(&self) -> T;
45}
46
47pub trait ActionCastRef<T> {
48 fn cast_ref(&self) -> &T;
49}
50
51impl<T: ActionTrait + Default + Clone> ActionCast<T> for Box<dyn ActionTrait>{
52 fn cast(&self) -> T{
53 if let Some(item) = (*self).downcast_ref::<T>() {
54 item.clone()
55 }
56 else {
57 T::default()
58 }
59 }
60}
61
62
63impl<T: ActionTrait + ActionDefaultRef> ActionCastRef<T> for Box<dyn ActionTrait>{
64 fn cast_ref(&self) -> &T{
65 if let Some(item) = (*self).downcast_ref::<T>() {
66 item
67 }
68 else {
69 T::default_ref()
70 }
71 }
72}
73
74impl<T: ActionTrait + ActionDefaultRef> ActionCastRef<T> for Option<std::sync::Arc<dyn ActionTrait>>{
75 fn cast_ref(&self) -> &T{
76 if let Some(item) = self{
77 if let Some(item) = item.downcast_ref::<T>() {
78 return item
79 }
80 }
81 T::default_ref()
82 }
83}
84
85impl Cx{
86 pub fn handle_action_receiver(&mut self){
87 while let Ok(action) = self.action_receiver.try_recv(){
88 self.new_actions.push(action);
89 }
90 self.handle_actions();
91 }
92
93 pub fn post_action(action:impl ActionTrait + Send){
98 ACTION_SENDER_GLOBAL.lock().unwrap().as_mut().unwrap().send(Box::new(action)).unwrap();
99 SignalToUI::set_action_signal();
100 }
101
102 pub fn action(&mut self, action: impl ActionTrait){
103 self.new_actions.push(Box::new(action));
104 }
105
106 pub fn extend_actions(&mut self, actions: ActionsBuf){
112 self.new_actions.extend(actions);
113 }
114
115 pub fn map_actions<F, G, R>(&mut self, f: F, g:G) -> R
116 where
117 F: FnOnce(&mut Cx) -> R,
118 G: FnOnce(&mut Cx, ActionsBuf)->ActionsBuf,
119 {
120 let start = self.new_actions.len();
121 let r = f(self);
122 let end = self.new_actions.len();
123 if start != end{
124 let buf = self.new_actions.drain(start..end).collect();
125 let buf = g(self, buf);
126 self.new_actions.extend(buf);
127 }
128 r
129 }
130
131 pub fn mutate_actions<F, G, R>(&mut self, f: F, g:G) -> R
132 where
133 F: FnOnce(&mut Cx) -> R,
134 G: FnOnce(&mut [Action]),
135 {
136 let start = self.new_actions.len();
137 let r = f(self);
138 let end = self.new_actions.len();
139 if start != end{
140 g(&mut self.new_actions[start..end]);
141 }
142 r
143 }
144
145 pub fn capture_actions<F>(&mut self, f: F) -> ActionsBuf
155 where
156 F: FnOnce(&mut Cx),
157 {
158 let mut actions = Vec::new();
159 std::mem::swap(&mut self.new_actions, &mut actions);
160 f(self);
161 std::mem::swap(&mut self.new_actions, &mut actions);
162 actions
163 }
164}