1use crate::store::Reaction;
2use crate::reactive_state_functions::*;
3use std::marker::PhantomData;
4use crate::observable::Observable;
5use crate::store::StorageKey;
6pub enum AllowUndo{}
9pub enum NoUndo{}
10pub enum IsAnAtomState{}
11pub enum IsAReactionState{}
12
13pub struct ReactiveStateAccess<T,U,A> {
18 pub id: StorageKey,
19
20 pub _phantom_data_stored_type: PhantomData<T>,
21 pub _phantom_data_undo : PhantomData<U>,
22 pub _phantom_data_accessor_type : PhantomData<A>,
23}
24
25impl<T,U,A> std::fmt::Debug for ReactiveStateAccess<T,U,A> {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 write!(f, "({:#?})", self.id)
28 }
29}
30impl<T,U,A> Clone for ReactiveStateAccess<T,U,A> {
32 fn clone(&self) -> ReactiveStateAccess<T,U,A> {
33 ReactiveStateAccess::<T,U,A> {
34 id: self.id,
35
36 _phantom_data_stored_type: PhantomData::<T>,
37 _phantom_data_undo : PhantomData::<U>,
38 _phantom_data_accessor_type : PhantomData::<A>,
39 }
40 }
41}
42
43
44impl<T,U,A> Copy for ReactiveStateAccess<T,U,A> {}
45
46impl<T,U,A> ReactiveStateAccess<T,U,A>
47where
48 T: 'static,
49{
50 pub fn new(id: StorageKey) -> ReactiveStateAccess<T,U,A> {
51 ReactiveStateAccess {
52 id,
53
54 _phantom_data_stored_type: PhantomData,
55 _phantom_data_undo: PhantomData,
56 _phantom_data_accessor_type: PhantomData,
57 }
58 }
59
60 pub fn insert_set(self, value: T) where Self :OverloadedUpdateStateAccess<T>{
62 self.overloaded_inert_set(value);
63 }
64
65
66 pub fn set(self, value: T) where Self :OverloadedUpdateStateAccess<T>{
68 self.overloaded_set(value);
69 }
70
71
72
73 pub fn remove(self) -> Option<T> {
74 remove_reactive_state_with_id(&self.id)
75 }
76
77 pub fn delete(self) {
78 self.remove();
79 }
80
81
82 pub fn undo(&self) where Self: OverloadedUpdateStateAccess<T> {
83 self.overloaded_undo();
84 }
85
86 pub fn update<F: FnOnce(&mut T) -> ()>(&self, func: F) where Self :OverloadedUpdateStateAccess<T>{
89 self.overloaded_update( func);
90 }
91
92 pub fn reset_to_default(&self) where Self :OverloadedUpdateStateAccess<T>{
93 self.overloaded_reset_to_default();
94 }
95
96
97 pub fn state_exists(self) -> bool {
98 reactive_state_exists_for_id::<T>(&self.id)
99 }
100
101 pub fn get_with<F: FnOnce(&T) -> R, R>(&self, func: F) -> R {
102 read_reactive_state_with_id(&self.id, func)
103 }
104
105
106
107 pub fn on_update<F: FnOnce() -> R,R>(&self, func:F) -> Option<R> {
108 let mut recalc = false ;
109 self.observe_with(|_| recalc = true);
110 if recalc {
111 Some(func())
112 } else {
113 None
114 }
115 }
116
117
118}
119
120
121pub trait CloneReactiveState<T>
123where
124 T: Clone + 'static,
125{
126 fn get(&self) -> T;
127 fn soft_get(&self) -> Option<T>;
128}
129
130impl<T,U,A> CloneReactiveState<T> for ReactiveStateAccess<T,U,A>
131where
132 T: Clone + 'static,
133{
134 fn get(&self) -> T {
136 clone_reactive_state_with_id::<T>(&self.id).expect("state should be present")
137 }
138
139 fn soft_get(&self) -> Option<T> {
140 clone_reactive_state_with_id::<T>(&self.id)
141 }
142}
143
144pub trait OverloadedUpdateStateAccess<T> where T:'static {
147 fn overloaded_update<F: FnOnce(&mut T) -> ()>(&self, func: F);
148 fn overloaded_reset_to_default(&self);
149 fn overloaded_undo(&self);
150 fn overloaded_inert_set(self, value: T);
151 fn overloaded_set(self, value: T);
152}
153
154
155impl <T> OverloadedUpdateStateAccess<T> for ReactiveStateAccess<T,NoUndo,IsAnAtomState> where T:'static
156{
157 fn overloaded_undo(&self){
158 panic!("cannot undo this atom is not undoable");
159 }
160
161
162 fn overloaded_reset_to_default(&self){
163 (clone_reactive_state_with_id::<Reaction>(&self.id).unwrap().func)();
165 execute_reaction_nodes(&self.id);
166
167 }
168
169
170
171 fn overloaded_update<F: FnOnce(&mut T) -> ()>(&self, func: F) {
172
173 update_atom_state_with_id(&self.id, func);
174
175 }
176
177 fn overloaded_inert_set(self, value: T) {
178 set_inert_atom_state_with_id(value, &self.id);
179 }
180
181 fn overloaded_set(self, value: T) {
182 set_atom_state_with_id(value, &self.id);
183 }
184}
185
186
187impl <T> OverloadedUpdateStateAccess<T> for ReactiveStateAccess<T,AllowUndo,IsAnAtomState>
188where T:Clone + 'static,
189{
190
191 fn overloaded_reset_to_default(&self){
192 (clone_reactive_state_with_id::<Reaction>(&self.id).unwrap().func)();
193 execute_reaction_nodes(&self.id);
194 }
195
196 fn overloaded_undo(&self){
197
198 undo_atom_state::<T,AllowUndo,IsAnAtomState>(&self.id)
199 }
200
201 fn overloaded_update<F: FnOnce(&mut T) -> ()>(&self, func: F) {
202 update_atom_state_with_id_with_undo(&self.id, func);
203 }
204
205 fn overloaded_inert_set(self, value: T) {
206 set_inert_atom_state_with_id_with_undo(value, &self.id);
207 }
208
209 fn overloaded_set(self, value: T) {
210 set_atom_state_with_id_with_undo(value, &self.id);
211 }
212}
213
214
215
216#[derive(Clone)]
220struct ChangedWrapper<T>(T);
221
222pub trait ChangedAtomState {
223 fn changed(&self) -> bool;
224}
225
226impl<T,U,A> ChangedAtomState for ReactiveStateAccess<T,U,A>
227where
228 T: Clone + 'static + PartialEq,
229{
230 fn changed(&self) -> bool {
231 if reactive_state_exists_for_id::<ChangedWrapper<T>>(&self.id){
232 read_reactive_state_with_id::<ChangedWrapper<T>,_,_>(&self.id, |old|
233 self.get_with(|current| &old.0==current )
234 )
235 } else {
236 set_inert_atom_state_with_id(ChangedWrapper(self.get()), &self.id);
237 true
238 }
239 }
240}
241impl<T,U,A> std::fmt::Display for ReactiveStateAccess<T,U,A>
243where
244 T: std::fmt::Display + 'static,
245{
246 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
247 self.get_with(|t| write!(f, "{}", t))
248 }
249}
250
251use std::ops::Add;
252use std::ops::Div;
253use std::ops::Mul;
254use std::ops::Sub;
255
256impl<T,U,A> Add for ReactiveStateAccess<T,U,A>
257where
258 T: Copy + Add<Output = T> + 'static,
259{
260 type Output = T;
261
262 fn add(self, other: Self) -> Self::Output {
263 self.get_with(|s| other.get_with(|o| *o + *s))
264 }
265}
266
267impl<T,U,A> Mul for ReactiveStateAccess<T,U,A>
268where
269 T: Copy + Mul<Output = T> + 'static,
270{
271 type Output = T;
272
273 fn mul(self, other: Self) -> Self::Output {
274 self.get_with(|s| other.get_with(|o| *o * *s))
275 }
276}
277
278impl<T,U,A> Div for ReactiveStateAccess<T,U,A>
279where
280 T: Copy + Div<Output = T> + 'static,
281{
282 type Output = T;
283
284 fn div(self, other: Self) -> Self::Output {
285 self.get_with(|s| other.get_with(|o| *o / *s))
286 }
287}
288
289impl<T,U,A> Sub for ReactiveStateAccess<T,U,A>
290where
291 T: Copy + Sub<Output = T> + 'static,
292{
293 type Output = T;
294
295 fn sub(self, other: Self) -> Self::Output {
296 self.get_with(|s| other.get_with(|o| *o - *s))
297 }
298}