1use crate::{
2 private::Sealed, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace, BorrowWindow,
3 Bounds, Element, ElementId, Entity, EntityId, Flatten, FocusHandle, FocusableView, IntoElement,
4 LayoutId, Model, Pixels, Point, Render, Size, ViewContext, VisualContext, WeakModel,
5 WindowContext,
6};
7use anyhow::{Context, Result};
8use std::{
9 any::TypeId,
10 hash::{Hash, Hasher},
11};
12
13pub struct View<V> {
14 pub model: Model<V>,
15}
16
17impl<V> Sealed for View<V> {}
18
19impl<V: 'static> Entity<V> for View<V> {
20 type Weak = WeakView<V>;
21
22 fn entity_id(&self) -> EntityId {
23 self.model.entity_id
24 }
25
26 fn downgrade(&self) -> Self::Weak {
27 WeakView {
28 model: self.model.downgrade(),
29 }
30 }
31
32 fn upgrade_from(weak: &Self::Weak) -> Option<Self>
33 where
34 Self: Sized,
35 {
36 let model = weak.model.upgrade()?;
37 Some(View { model })
38 }
39}
40
41impl<V: 'static> View<V> {
42 /// Convert this strong view reference into a weak view reference.
43 pub fn downgrade(&self) -> WeakView<V> {
44 Entity::downgrade(self)
45 }
46
47 pub fn update<C, R>(
48 &self,
49 cx: &mut C,
50 f: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
51 ) -> C::Result<R>
52 where
53 C: VisualContext,
54 {
55 cx.update_view(self, f)
56 }
57
58 pub fn read<'a>(&self, cx: &'a AppContext) -> &'a V {
59 self.model.read(cx)
60 }
61
62 // pub fn render_with<E>(&self, component: E) -> RenderViewWith<E, V>
63 // where
64 // E: 'static + Element,
65 // {
66 // RenderViewWith {
67 // view: self.clone(),
68 // element: Some(component),
69 // }
70 // }
71
72 pub fn focus_handle(&self, cx: &AppContext) -> FocusHandle
73 where
74 V: FocusableView,
75 {
76 self.read(cx).focus_handle(cx)
77 }
78}
79
80impl<V: Render> Element for View<V> {
81 type State = Option<AnyElement>;
82
83 fn layout(
84 &mut self,
85 _state: Option<Self::State>,
86 cx: &mut WindowContext,
87 ) -> (LayoutId, Self::State) {
88 let mut element = self.update(cx, |view, cx| view.render(cx).into_any());
89 let layout_id = element.layout(cx);
90 (layout_id, Some(element))
91 }
92
93 fn paint(self, _: Bounds<Pixels>, element: &mut Self::State, cx: &mut WindowContext) {
94 element.take().unwrap().paint(cx);
95 }
96}
97
98impl<V> Clone for View<V> {
99 fn clone(&self) -> Self {
100 Self {
101 model: self.model.clone(),
102 }
103 }
104}
105
106impl<V> Hash for View<V> {
107 fn hash<H: Hasher>(&self, state: &mut H) {
108 self.model.hash(state);
109 }
110}
111
112impl<V> PartialEq for View<V> {
113 fn eq(&self, other: &Self) -> bool {
114 self.model == other.model
115 }
116}
117
118impl<V> Eq for View<V> {}
119
120pub struct WeakView<V> {
121 pub(crate) model: WeakModel<V>,
122}
123
124impl<V: 'static> WeakView<V> {
125 pub fn entity_id(&self) -> EntityId {
126 self.model.entity_id
127 }
128
129 pub fn upgrade(&self) -> Option<View<V>> {
130 Entity::upgrade_from(self)
131 }
132
133 pub fn update<C, R>(
134 &self,
135 cx: &mut C,
136 f: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
137 ) -> Result<R>
138 where
139 C: VisualContext,
140 Result<C::Result<R>>: Flatten<R>,
141 {
142 let view = self.upgrade().context("error upgrading view")?;
143 Ok(view.update(cx, f)).flatten()
144 }
145}
146
147impl<V> Clone for WeakView<V> {
148 fn clone(&self) -> Self {
149 Self {
150 model: self.model.clone(),
151 }
152 }
153}
154
155impl<V> Hash for WeakView<V> {
156 fn hash<H: Hasher>(&self, state: &mut H) {
157 self.model.hash(state);
158 }
159}
160
161impl<V> PartialEq for WeakView<V> {
162 fn eq(&self, other: &Self) -> bool {
163 self.model == other.model
164 }
165}
166
167impl<V> Eq for WeakView<V> {}
168
169#[derive(Clone, Debug)]
170pub struct AnyView {
171 model: AnyModel,
172 layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, AnyElement),
173 paint: fn(&AnyView, AnyElement, &mut WindowContext),
174}
175
176impl AnyView {
177 pub fn downgrade(&self) -> AnyWeakView {
178 AnyWeakView {
179 model: self.model.downgrade(),
180 layout: self.layout,
181 paint: self.paint,
182 }
183 }
184
185 pub fn downcast<T: 'static>(self) -> Result<View<T>, Self> {
186 match self.model.downcast() {
187 Ok(model) => Ok(View { model }),
188 Err(model) => Err(Self {
189 model,
190 layout: self.layout,
191 paint: self.paint,
192 }),
193 }
194 }
195
196 pub fn entity_type(&self) -> TypeId {
197 self.model.entity_type
198 }
199
200 pub fn entity_id(&self) -> EntityId {
201 self.model.entity_id()
202 }
203
204 pub(crate) fn draw(
205 &self,
206 origin: Point<Pixels>,
207 available_space: Size<AvailableSpace>,
208 cx: &mut WindowContext,
209 ) {
210 cx.with_absolute_element_offset(origin, |cx| {
211 let (layout_id, rendered_element) = (self.layout)(self, cx);
212 cx.compute_layout(layout_id, available_space);
213 (self.paint)(self, rendered_element, cx);
214 })
215 }
216}
217
218impl<V: Render> From<View<V>> for AnyView {
219 fn from(value: View<V>) -> Self {
220 AnyView {
221 model: value.model.into_any(),
222 layout: any_view::layout::<V>,
223 paint: any_view::paint::<V>,
224 }
225 }
226}
227
228impl Element for AnyView {
229 type State = Option<AnyElement>;
230
231 fn layout(
232 &mut self,
233 _state: Option<Self::State>,
234 cx: &mut WindowContext,
235 ) -> (LayoutId, Self::State) {
236 let (layout_id, state) = (self.layout)(self, cx);
237 (layout_id, Some(state))
238 }
239
240 fn paint(self, _: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) {
241 debug_assert!(
242 state.is_some(),
243 "state is None. Did you include an AnyView twice in the tree?"
244 );
245 (self.paint)(&self, state.take().unwrap(), cx)
246 }
247}
248
249impl<V: 'static + Render> IntoElement for View<V> {
250 type Element = View<V>;
251
252 fn element_id(&self) -> Option<ElementId> {
253 Some(ElementId::from_entity_id(self.model.entity_id))
254 }
255
256 fn into_element(self) -> Self::Element {
257 self
258 }
259}
260
261impl IntoElement for AnyView {
262 type Element = Self;
263
264 fn element_id(&self) -> Option<ElementId> {
265 Some(ElementId::from_entity_id(self.model.entity_id))
266 }
267
268 fn into_element(self) -> Self::Element {
269 self
270 }
271}
272
273pub struct AnyWeakView {
274 model: AnyWeakModel,
275 layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, AnyElement),
276 paint: fn(&AnyView, AnyElement, &mut WindowContext),
277}
278
279impl AnyWeakView {
280 pub fn upgrade(&self) -> Option<AnyView> {
281 let model = self.model.upgrade()?;
282 Some(AnyView {
283 model,
284 layout: self.layout,
285 paint: self.paint,
286 })
287 }
288}
289
290impl<V: 'static + Render> From<WeakView<V>> for AnyWeakView {
291 fn from(view: WeakView<V>) -> Self {
292 Self {
293 model: view.model.into(),
294 layout: any_view::layout::<V>,
295 paint: any_view::paint::<V>,
296 }
297 }
298}
299
300impl<T, E> Render for T
301where
302 T: 'static + FnMut(&mut WindowContext) -> E,
303 E: 'static + Send + Element,
304{
305 type Element = E;
306
307 fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
308 (self)(cx)
309 }
310}
311
312mod any_view {
313 use crate::{AnyElement, AnyView, Element, LayoutId, Render, WindowContext};
314
315 pub(crate) fn layout<V: 'static + Render>(
316 view: &AnyView,
317 cx: &mut WindowContext,
318 ) -> (LayoutId, AnyElement) {
319 let view = view.clone().downcast::<V>().unwrap();
320 let mut element = view.update(cx, |view, cx| view.render(cx).into_any());
321 let layout_id = element.layout(cx);
322 (layout_id, element)
323 }
324
325 pub(crate) fn paint<V: 'static + Render>(
326 _view: &AnyView,
327 element: AnyElement,
328 cx: &mut WindowContext,
329 ) {
330 element.paint(cx);
331 }
332}