view.rs

  1use parking_lot::Mutex;
  2
  3use crate::{
  4    AnyBox, AnyElement, BorrowWindow, Bounds, Element, ElementId, EntityId, Handle, IntoAnyElement,
  5    LayoutId, Pixels, ViewContext, WindowContext,
  6};
  7use std::{marker::PhantomData, sync::Arc};
  8
  9pub struct View<V: Send + Sync> {
 10    state: Handle<V>,
 11    render: Arc<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyElement<V> + Send + Sync + 'static>,
 12}
 13
 14impl<V: 'static + Send + Sync> View<V> {
 15    pub fn into_any(self) -> AnyView {
 16        AnyView {
 17            view: Arc::new(Mutex::new(self)),
 18        }
 19    }
 20}
 21
 22impl<V: Send + Sync> Clone for View<V> {
 23    fn clone(&self) -> Self {
 24        Self {
 25            state: self.state.clone(),
 26            render: self.render.clone(),
 27        }
 28    }
 29}
 30
 31pub fn view<V, E>(
 32    state: Handle<V>,
 33    render: impl Fn(&mut V, &mut ViewContext<V>) -> E + Send + Sync + 'static,
 34) -> View<V>
 35where
 36    E: IntoAnyElement<V>,
 37    V: 'static + Send + Sync,
 38{
 39    View {
 40        state,
 41        render: Arc::new(move |state, cx| render(state, cx).into_any()),
 42    }
 43}
 44
 45impl<V: 'static + Send + Sync, ParentViewState: 'static + Send + Sync>
 46    IntoAnyElement<ParentViewState> for View<V>
 47{
 48    fn into_any(self) -> AnyElement<ParentViewState> {
 49        AnyElement::new(EraseViewState {
 50            view: self,
 51            parent_view_state_type: PhantomData,
 52        })
 53    }
 54}
 55
 56impl<V: 'static + Send + Sync> Element for View<V> {
 57    type ViewState = ();
 58    type ElementState = AnyElement<V>;
 59
 60    fn id(&self) -> Option<crate::ElementId> {
 61        Some(ElementId::View(self.state.id))
 62    }
 63
 64    fn initialize(
 65        &mut self,
 66        _: &mut (),
 67        _: Option<Self::ElementState>,
 68        cx: &mut ViewContext<()>,
 69    ) -> Self::ElementState {
 70        self.state.update(cx, |state, cx| (self.render)(state, cx))
 71    }
 72
 73    fn layout(
 74        &mut self,
 75        _: &mut (),
 76        element: &mut Self::ElementState,
 77        cx: &mut ViewContext<()>,
 78    ) -> LayoutId {
 79        self.state.update(cx, |state, cx| element.layout(state, cx))
 80    }
 81
 82    fn paint(
 83        &mut self,
 84        _: Bounds<Pixels>,
 85        _: &mut (),
 86        element: &mut Self::ElementState,
 87        cx: &mut ViewContext<()>,
 88    ) {
 89        self.state
 90            .update(cx, |state, cx| element.paint(state, None, cx))
 91    }
 92}
 93
 94struct EraseViewState<V: 'static + Send + Sync, ParentV> {
 95    view: View<V>,
 96    parent_view_state_type: PhantomData<ParentV>,
 97}
 98
 99impl<V, ParentV> IntoAnyElement<ParentV> for EraseViewState<V, ParentV>
100where
101    V: 'static + Send + Sync,
102    ParentV: 'static + Send + Sync,
103{
104    fn into_any(self) -> AnyElement<ParentV> {
105        AnyElement::new(self)
106    }
107}
108
109impl<V, ParentV> Element for EraseViewState<V, ParentV>
110where
111    V: 'static + Send + Sync,
112    ParentV: 'static + Send + Sync,
113{
114    type ViewState = ParentV;
115    type ElementState = AnyBox;
116
117    fn id(&self) -> Option<crate::ElementId> {
118        Element::id(&self.view)
119    }
120
121    fn initialize(
122        &mut self,
123        _: &mut Self::ViewState,
124        _: Option<Self::ElementState>,
125        cx: &mut ViewContext<Self::ViewState>,
126    ) -> Self::ElementState {
127        ViewObject::initialize(&mut self.view, cx)
128    }
129
130    fn layout(
131        &mut self,
132        _: &mut Self::ViewState,
133        element: &mut Self::ElementState,
134        cx: &mut ViewContext<Self::ViewState>,
135    ) -> LayoutId {
136        ViewObject::layout(&mut self.view, element, cx)
137    }
138
139    fn paint(
140        &mut self,
141        bounds: Bounds<Pixels>,
142        _: &mut Self::ViewState,
143        element: &mut Self::ElementState,
144        cx: &mut ViewContext<Self::ViewState>,
145    ) {
146        ViewObject::paint(&mut self.view, bounds, element, cx)
147    }
148}
149
150trait ViewObject: 'static + Send + Sync {
151    fn entity_id(&self) -> EntityId;
152    fn initialize(&mut self, cx: &mut WindowContext) -> AnyBox;
153    fn layout(&mut self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId;
154    fn paint(&mut self, bounds: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext);
155}
156
157impl<V: Send + Sync + 'static> ViewObject for View<V> {
158    fn entity_id(&self) -> EntityId {
159        self.state.id
160    }
161
162    fn initialize(&mut self, cx: &mut WindowContext) -> AnyBox {
163        cx.with_element_id(self.entity_id(), |cx| {
164            self.state
165                .update(cx, |state, cx| Box::new((self.render)(state, cx)) as AnyBox)
166        })
167    }
168
169    fn layout(&mut self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId {
170        cx.with_element_id(self.entity_id(), |cx| {
171            self.state.update(cx, |state, cx| {
172                let element = element.downcast_mut::<AnyElement<V>>().unwrap();
173                element.layout(state, cx)
174            })
175        })
176    }
177
178    fn paint(&mut self, _: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext) {
179        cx.with_element_id(self.entity_id(), |cx| {
180            self.state.update(cx, |state, cx| {
181                let element = element.downcast_mut::<AnyElement<V>>().unwrap();
182                element.paint(state, None, cx);
183            });
184        });
185    }
186}
187
188pub struct AnyView {
189    view: Arc<Mutex<dyn ViewObject>>,
190}
191
192impl<ParentV> IntoAnyElement<ParentV> for AnyView
193where
194    ParentV: 'static + Send + Sync,
195{
196    fn into_any(self) -> AnyElement<ParentV> {
197        AnyElement::new(EraseAnyViewState {
198            view: self,
199            parent_view_state_type: PhantomData,
200        })
201    }
202}
203
204impl Element for AnyView {
205    type ViewState = ();
206    type ElementState = AnyBox;
207
208    fn id(&self) -> Option<crate::ElementId> {
209        Some(ElementId::View(self.view.lock().entity_id()))
210    }
211
212    fn initialize(
213        &mut self,
214        _: &mut Self::ViewState,
215        _: Option<Self::ElementState>,
216        cx: &mut ViewContext<Self::ViewState>,
217    ) -> Self::ElementState {
218        self.view.lock().initialize(cx)
219    }
220
221    fn layout(
222        &mut self,
223        _: &mut Self::ViewState,
224        element: &mut Self::ElementState,
225        cx: &mut ViewContext<Self::ViewState>,
226    ) -> LayoutId {
227        self.view.lock().layout(element, cx)
228    }
229
230    fn paint(
231        &mut self,
232        bounds: Bounds<Pixels>,
233        _: &mut (),
234        element: &mut AnyBox,
235        cx: &mut ViewContext<Self::ViewState>,
236    ) {
237        self.view.lock().paint(bounds, element, cx)
238    }
239}
240
241struct EraseAnyViewState<ParentViewState> {
242    view: AnyView,
243    parent_view_state_type: PhantomData<ParentViewState>,
244}
245
246impl<ParentV> IntoAnyElement<ParentV> for EraseAnyViewState<ParentV>
247where
248    ParentV: 'static + Send + Sync,
249{
250    fn into_any(self) -> AnyElement<ParentV> {
251        AnyElement::new(self)
252    }
253}
254
255impl<ParentV> Element for EraseAnyViewState<ParentV>
256where
257    ParentV: 'static + Send + Sync,
258{
259    type ViewState = ParentV;
260    type ElementState = AnyBox;
261
262    fn id(&self) -> Option<crate::ElementId> {
263        Element::id(&self.view)
264    }
265
266    fn initialize(
267        &mut self,
268        _: &mut Self::ViewState,
269        _: Option<Self::ElementState>,
270        cx: &mut ViewContext<Self::ViewState>,
271    ) -> Self::ElementState {
272        self.view.view.lock().initialize(cx)
273    }
274
275    fn layout(
276        &mut self,
277        _: &mut Self::ViewState,
278        element: &mut Self::ElementState,
279        cx: &mut ViewContext<Self::ViewState>,
280    ) -> LayoutId {
281        self.view.view.lock().layout(element, cx)
282    }
283
284    fn paint(
285        &mut self,
286        bounds: Bounds<Pixels>,
287        _: &mut Self::ViewState,
288        element: &mut Self::ElementState,
289        cx: &mut ViewContext<Self::ViewState>,
290    ) {
291        self.view.view.lock().paint(bounds, element, cx)
292    }
293}
294
295impl Clone for AnyView {
296    fn clone(&self) -> Self {
297        Self {
298            view: self.view.clone(),
299        }
300    }
301}