Skip to main content

perspective_viewer/model/
structural.rs

1// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2// ┃ ██████ ██████ ██████       █      █      █      █      █ █▄  ▀███ █       ┃
3// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█  ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄  ▀█ █ ▀▀▀▀▀ ┃
4// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄   █ ▄▄▄▄▄ ┃
5// ┃ █      ██████ █  ▀█▄       █ ██████      █      ███▌▐███ ███████▄ █       ┃
6// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7// ┃ Copyright (c) 2017, the Perspective Authors.                              ┃
8// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9// ┃ This file is part of the Perspective library, distributed under the terms ┃
10// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13//! A simple "structurally-typed" method extension implementation.  This
14//! collection of `trait`s allows methods to be automatically defined for
15//! `struct`s only if the define accessors for the necessary applications state
16//! objects (which are conviently derivable with the `derive_model!` macro).
17
18use yew::Component;
19
20use crate::custom_events::*;
21use crate::dragdrop::*;
22use crate::presentation::*;
23use crate::renderer::*;
24use crate::root::*;
25use crate::session::*;
26
27pub trait HasCustomEvents {
28    fn custom_events(&self) -> &'_ CustomEvents;
29}
30
31pub trait HasDragDrop {
32    fn dragdrop(&self) -> &'_ DragDrop;
33}
34
35pub trait HasPresentation {
36    fn presentation(&self) -> &'_ Presentation;
37}
38
39pub trait HasRoot {
40    /// Use an assoociated type to prevent a (circular) dependency on
41    /// [`crate::components`].
42    type RootComponent: Component;
43    fn root(&self) -> &'_ Root<Self::RootComponent>;
44}
45
46pub trait HasRenderer {
47    fn renderer(&self) -> &'_ Renderer;
48}
49
50pub trait HasSession {
51    fn session(&self) -> &'_ Session;
52}
53
54impl HasSession for Session {
55    fn session(&self) -> &'_ Session {
56        self
57    }
58}
59
60#[macro_export]
61macro_rules! PerspectiveProperties {
62    // (impl @tuple $name:ident CustomEvents $x:tt) => {
63    //     impl $crate::model::HasCustomEvents for $name {
64    //         fn custom_events(&self) -> &'_ CustomEvents {
65    //             &self.$x
66    //         }
67    //     }
68    // };
69
70    // (impl @tuple $name:ident DragDrop $x:tt) => {
71    //     impl $crate::model::HasDragDrop for $name {
72    //         fn dragdrop(&self) -> &'_ DragDrop {
73    //             &self.$x
74    //         }
75    //     }
76    // };
77
78    // (impl @tuple $name:ident Presentatio $x:tt) => {
79    //     impl $crate::model::HasPresentation for $name {
80    //         fn presentation(&self) -> &'_ Presentation {
81    //             &self.$x
82    //         }
83    //     }
84    // };
85
86    // (impl @tuple $name:ident Renderer $x:tt) => {
87    //     impl $crate::model::HasRenderer for $name {
88    //         fn renderer(&self) -> &'_ Renderer {
89    //             &self.$x
90    //         }
91    //     }
92    // };
93
94    // (impl @tuple $name:ident Root $x:tt) => {
95    //     impl $crate::model::HasRoot for $name {
96    //         type RootComponent = $crate::components::viewer::PerspectiveViewer;
97    //         fn root(&self) -> &'_ Root<Self::RootComponent> {
98    //             &self.$x
99    //         }
100    //     }
101    // };
102
103    // (impl @tuple $name:ident Session $x:tt) => {
104    //     impl $crate::model::HasSession for $name {
105    //         fn session(&self) -> &'_ Session {
106    //             &self.$x
107    //         }
108    //     }
109    // };
110
111    // (impl @tuple $name:ident *_x:tt $x:tt) => {};
112
113    (impl @field $name:ident custom_events $value:ty) => {
114        impl $crate::model::HasCustomEvents for $name {
115            fn custom_events(&self) -> &'_ $value {
116                &self.custom_events
117            }
118        }
119    };
120
121    (impl @field $name:ident dragdrop $value:ty) => {
122        impl $crate::model::HasDragDrop for $name {
123            fn dragdrop(&self) -> &'_ $value {
124                &self.dragdrop
125            }
126        }
127    };
128
129    (impl @field $name:ident presentation $value:ty) => {
130        impl $crate::model::HasPresentation for $name {
131            fn presentation(&self) -> &'_ $value {
132                &self.presentation
133            }
134        }
135    };
136
137    (impl @field $name:ident renderer $value:ty) => {
138        impl $crate::model::HasRenderer for $name {
139            fn renderer(&self) -> &'_ $value {
140                &self.renderer
141            }
142        }
143    };
144
145    (impl @field $name:ident root $value:ty) => {
146        impl $crate::model::HasRoot for $name {
147            type RootComponent = $crate::components::viewer::PerspectiveViewer;
148            fn root(&self) -> &'_ $value {
149                &self.root
150            }
151        }
152    };
153
154    (impl @field $name:ident session $value:ty) => {
155        impl $crate::model::HasSession for $name {
156            fn session(&self) -> &'_ $value {
157                &self.session
158            }
159        }
160    };
161
162    (impl @field $name:ident $x:ident $value:ty) => {};
163
164    (impl @fields_provider $name:ident {$($x:tt : $y:ty,)*} custom_events, $($field:ident,)*) => {
165        PerspectiveProperties!(impl @fields_provider $name { custom_events : CustomEvents, $($x : $y,)*} $($field,)*);
166    };
167
168    (impl @fields_provider $name:ident {$($x:tt : $y:ty,)*} dragdrop, $($field:ident,)*) => {
169        PerspectiveProperties!(impl @fields_provider $name { dragdrop : DragDrop, $($x : $y,)*} $($field,)*);
170    };
171
172    (impl @fields_provider $name:ident {$($x:tt : $y:ty,)*} presentation, $($field:ident,)*) => {
173        PerspectiveProperties!(impl @fields_provider $name { presentation : Presentation, $($x : $y,)*} $($field,)*);
174    };
175
176    (impl @fields_provider $name:ident {$($x:tt : $y:ty,)*} renderer, $($field:ident,)*) => {
177        PerspectiveProperties!(impl @fields_provider $name { renderer : Renderer, $($x : $y,)*} $($field,)*);
178    };
179
180     (impl @fields_provider $name:ident {$($x:tt : $y:ty,)*} root, $($field:ident,)*) => {
181        PerspectiveProperties!(impl @fields_provider $name { root : Root<$crate::components::viewer::PerspectiveViewer>, $($x : $y,)*} $($field,)*);
182    };
183
184    (impl @fields_provider $name:ident {$($x:tt : $y:ty,)*} session, $($field:ident,)*) => {
185        PerspectiveProperties!(impl @fields_provider $name { session : Session, $($x : $y,)*} $($field,)*);
186    };
187
188    (impl @fields_provider $name:ident {$($x:tt : $y:ty,)*} $_x:ident, $($field:ident,)*) => {
189        PerspectiveProperties!(impl @fields_provider $name {$($x : $y,)*} $($field,)*);
190    };
191
192    (impl @fields_provider $name:ident {}) => {};
193
194    (impl @fields_provider $name:ident {$($x:tt : $y:ty,)*}) => {
195        perspective_client::vendor::paste::paste! {
196            #[derive(PartialEq, Clone)]
197            pub struct [< $name State >] {
198                $($x: $y,)*
199            }
200
201            impl $crate::model::StateProvider for $name {
202                type State = [< $name State >];
203                fn clone_state(&self) -> Self::State {
204                    Self::State {
205                        $($x : self.$x.clone(),)*
206                    }
207                }
208            }
209
210            PerspectiveProperties!(impl @fields [< $name State >] $($x : $y,)*);
211        }
212    };
213
214    (impl @fields $name:ident $field:ident : $value:ty, $($field_tail:ident : $value_tail:ty,)*) => {
215        PerspectiveProperties!(impl @field $name $field $value);
216        PerspectiveProperties!(impl @fields $name $($field_tail : $value_tail,)*);
217    };
218
219    (impl @fields $name:ident) => {};
220
221    // (impl @tuples $name:ident $value:tt : $acc:tt, $($value_tail:tt : $acc_tail:tt,)*) => {
222    //     PerspectiveProperties!(impl @tuple $name $value $acc);
223    //     PerspectiveProperties!(impl @tuples $name $($value_tail : $acc_tail,)*);
224    // };
225
226    // (impl @tuples $name:ident) => {};
227
228    ($(#[$m:meta])* $pub:vis struct $name:ident { $($(#[$_m:meta])* $_p:vis $field:ident : $value:ty),* $(,)? }) => {
229        PerspectiveProperties!(impl @fields $name $($field : $value,)*);
230        PerspectiveProperties!(impl @fields_provider $name {} $($field,)*);
231    };
232
233    // ($(#[$m:meta])* $pub:vis struct $name:ident ( $($(#[$_m:meta])* $value:tt $(< $_ttt:ty >)?),* $(,)? );) => {
234    //     PerspectiveProperties!(impl @tuples $name $($value : ${index()} ,)*);
235    // };
236}
237
238pub trait StateProvider {
239    type State: Clone + 'static;
240
241    /// Clones _just_ the state objects fields into a new dedicated state
242    /// struct (generated by [`PerspectiveProperties`]).
243    fn clone_state(&self) -> Self::State;
244}