1use crate::{
2 AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, Size, ViewContext,
3 WindowContext,
4};
5use derive_more::{Deref, DerefMut};
6pub(crate) use smallvec::SmallVec;
7use std::{any::Any, fmt::Debug};
8
9pub trait Render: 'static + Sized {
10 type Element: Element + 'static;
11
12 fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element;
13}
14
15pub trait IntoElement: Sized {
16 type Element: Element + 'static;
17
18 fn element_id(&self) -> Option<ElementId>;
19
20 fn into_element(self) -> Self::Element;
21
22 fn into_any_element(self) -> AnyElement {
23 self.into_element().into_any()
24 }
25
26 fn draw<T, R>(
27 self,
28 origin: Point<Pixels>,
29 available_space: Size<T>,
30 cx: &mut WindowContext,
31 f: impl FnOnce(&mut <Self::Element as Element>::State, &mut WindowContext) -> R,
32 ) -> R
33 where
34 T: Clone + Default + Debug + Into<AvailableSpace>,
35 {
36 let element = self.into_element();
37 let element_id = element.element_id();
38 let element = DrawableElement {
39 element: Some(element),
40 phase: ElementDrawPhase::Start,
41 };
42
43 let frame_state =
44 DrawableElement::draw(element, origin, available_space.map(Into::into), cx);
45
46 if let Some(mut frame_state) = frame_state {
47 f(&mut frame_state, cx)
48 } else {
49 cx.with_element_state(element_id.unwrap(), |element_state, cx| {
50 let mut element_state = element_state.unwrap();
51 let result = f(&mut element_state, cx);
52 (result, element_state)
53 })
54 }
55 }
56
57 fn map<U>(self, f: impl FnOnce(Self) -> U) -> U
58 where
59 Self: Sized,
60 U: IntoElement,
61 {
62 f(self)
63 }
64
65 fn when(self, condition: bool, then: impl FnOnce(Self) -> Self) -> Self
66 where
67 Self: Sized,
68 {
69 self.map(|this| if condition { then(this) } else { this })
70 }
71
72 fn when_some<T>(self, option: Option<T>, then: impl FnOnce(Self, T) -> Self) -> Self
73 where
74 Self: Sized,
75 {
76 self.map(|this| {
77 if let Some(value) = option {
78 then(this, value)
79 } else {
80 this
81 }
82 })
83 }
84}
85
86pub trait Element: 'static + IntoElement {
87 type State: 'static;
88
89 fn layout(
90 &mut self,
91 state: Option<Self::State>,
92 cx: &mut WindowContext,
93 ) -> (LayoutId, Self::State);
94
95 fn paint(self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext);
96
97 fn into_any(self) -> AnyElement {
98 AnyElement::new(self)
99 }
100}
101
102pub trait RenderOnce: 'static {
103 type Rendered: IntoElement;
104
105 fn render(self, cx: &mut WindowContext) -> Self::Rendered;
106}
107
108pub struct Component<C> {
109 component: Option<C>,
110}
111
112pub struct CompositeElementState<C: RenderOnce> {
113 rendered_element: Option<<C::Rendered as IntoElement>::Element>,
114 rendered_element_state: Option<<<C::Rendered as IntoElement>::Element as Element>::State>,
115}
116
117impl<C> Component<C> {
118 pub fn new(component: C) -> Self {
119 Component {
120 component: Some(component),
121 }
122 }
123}
124
125impl<C: RenderOnce> Element for Component<C> {
126 type State = CompositeElementState<C>;
127
128 fn layout(
129 &mut self,
130 state: Option<Self::State>,
131 cx: &mut WindowContext,
132 ) -> (LayoutId, Self::State) {
133 let mut element = self.component.take().unwrap().render(cx).into_element();
134 if let Some(element_id) = element.element_id() {
135 let layout_id =
136 cx.with_element_state(element_id, |state, cx| element.layout(state, cx));
137 let state = CompositeElementState {
138 rendered_element: Some(element),
139 rendered_element_state: None,
140 };
141 (layout_id, state)
142 } else {
143 let (layout_id, state) =
144 element.layout(state.and_then(|s| s.rendered_element_state), cx);
145 let state = CompositeElementState {
146 rendered_element: Some(element),
147 rendered_element_state: Some(state),
148 };
149 (layout_id, state)
150 }
151 }
152
153 fn paint(self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) {
154 let element = state.rendered_element.take().unwrap();
155 if let Some(element_id) = element.element_id() {
156 cx.with_element_state(element_id, |element_state, cx| {
157 let mut element_state = element_state.unwrap();
158 element.paint(bounds, &mut element_state, cx);
159 ((), element_state)
160 });
161 } else {
162 element.paint(
163 bounds,
164 &mut state.rendered_element_state.as_mut().unwrap(),
165 cx,
166 );
167 }
168 }
169}
170
171impl<C: RenderOnce> IntoElement for Component<C> {
172 type Element = Self;
173
174 fn element_id(&self) -> Option<ElementId> {
175 None
176 }
177
178 fn into_element(self) -> Self::Element {
179 self
180 }
181}
182
183#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
184pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
185
186pub trait ParentElement {
187 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>;
188
189 fn child(mut self, child: impl IntoElement) -> Self
190 where
191 Self: Sized,
192 {
193 self.children_mut().push(child.into_element().into_any());
194 self
195 }
196
197 fn children(mut self, children: impl IntoIterator<Item = impl IntoElement>) -> Self
198 where
199 Self: Sized,
200 {
201 self.children_mut()
202 .extend(children.into_iter().map(|child| child.into_any_element()));
203 self
204 }
205}
206
207trait ElementObject {
208 fn element_id(&self) -> Option<ElementId>;
209
210 fn layout(&mut self, cx: &mut WindowContext) -> LayoutId;
211
212 fn paint(&mut self, cx: &mut WindowContext);
213
214 fn measure(
215 &mut self,
216 available_space: Size<AvailableSpace>,
217 cx: &mut WindowContext,
218 ) -> Size<Pixels>;
219
220 fn draw(
221 &mut self,
222 origin: Point<Pixels>,
223 available_space: Size<AvailableSpace>,
224 cx: &mut WindowContext,
225 );
226}
227
228pub struct DrawableElement<E: Element> {
229 element: Option<E>,
230 phase: ElementDrawPhase<E::State>,
231}
232
233#[derive(Default)]
234enum ElementDrawPhase<S> {
235 #[default]
236 Start,
237 LayoutRequested {
238 layout_id: LayoutId,
239 frame_state: Option<S>,
240 },
241 LayoutComputed {
242 layout_id: LayoutId,
243 available_space: Size<AvailableSpace>,
244 frame_state: Option<S>,
245 },
246}
247
248/// A wrapper around an implementer of [Element] that allows it to be drawn in a window.
249impl<E: Element> DrawableElement<E> {
250 fn new(element: E) -> Self {
251 DrawableElement {
252 element: Some(element),
253 phase: ElementDrawPhase::Start,
254 }
255 }
256
257 fn element_id(&self) -> Option<ElementId> {
258 self.element.as_ref()?.element_id()
259 }
260
261 fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
262 let (layout_id, frame_state) = if let Some(id) = self.element.as_ref().unwrap().element_id()
263 {
264 let layout_id = cx.with_element_state(id, |element_state, cx| {
265 self.element.as_mut().unwrap().layout(element_state, cx)
266 });
267 (layout_id, None)
268 } else {
269 let (layout_id, frame_state) = self.element.as_mut().unwrap().layout(None, cx);
270 (layout_id, Some(frame_state))
271 };
272
273 self.phase = ElementDrawPhase::LayoutRequested {
274 layout_id,
275 frame_state,
276 };
277 layout_id
278 }
279
280 fn paint(mut self, cx: &mut WindowContext) -> Option<E::State> {
281 match self.phase {
282 ElementDrawPhase::LayoutRequested {
283 layout_id,
284 frame_state,
285 }
286 | ElementDrawPhase::LayoutComputed {
287 layout_id,
288 frame_state,
289 ..
290 } => {
291 let bounds = cx.layout_bounds(layout_id);
292
293 if let Some(mut frame_state) = frame_state {
294 self.element
295 .take()
296 .unwrap()
297 .paint(bounds, &mut frame_state, cx);
298 Some(frame_state)
299 } else {
300 let element_id = self
301 .element
302 .as_ref()
303 .unwrap()
304 .element_id()
305 .expect("if we don't have frame state, we should have element state");
306 cx.with_element_state(element_id, |element_state, cx| {
307 let mut element_state = element_state.unwrap();
308 self.element
309 .take()
310 .unwrap()
311 .paint(bounds, &mut element_state, cx);
312 ((), element_state)
313 });
314 None
315 }
316 }
317
318 _ => panic!("must call layout before paint"),
319 }
320 }
321
322 fn measure(
323 &mut self,
324 available_space: Size<AvailableSpace>,
325 cx: &mut WindowContext,
326 ) -> Size<Pixels> {
327 if matches!(&self.phase, ElementDrawPhase::Start) {
328 self.layout(cx);
329 }
330
331 let layout_id = match &mut self.phase {
332 ElementDrawPhase::LayoutRequested {
333 layout_id,
334 frame_state,
335 } => {
336 cx.compute_layout(*layout_id, available_space);
337 let layout_id = *layout_id;
338 self.phase = ElementDrawPhase::LayoutComputed {
339 layout_id,
340 available_space,
341 frame_state: frame_state.take(),
342 };
343 layout_id
344 }
345 ElementDrawPhase::LayoutComputed {
346 layout_id,
347 available_space: prev_available_space,
348 ..
349 } => {
350 if available_space != *prev_available_space {
351 cx.compute_layout(*layout_id, available_space);
352 *prev_available_space = available_space;
353 }
354 *layout_id
355 }
356 _ => panic!("cannot measure after painting"),
357 };
358
359 cx.layout_bounds(layout_id).size
360 }
361
362 fn draw(
363 mut self,
364 origin: Point<Pixels>,
365 available_space: Size<AvailableSpace>,
366 cx: &mut WindowContext,
367 ) -> Option<E::State> {
368 self.measure(available_space, cx);
369 cx.with_absolute_element_offset(origin, |cx| self.paint(cx))
370 }
371}
372
373// impl<V: 'static, E: Element> Element for DrawableElement<V, E> {
374// type State = <E::Element as Element>::State;
375
376// fn layout(
377// &mut self,
378// element_state: Option<Self::State>,
379// cx: &mut WindowContext,
380// ) -> (LayoutId, Self::State) {
381
382// }
383
384// fn paint(
385// self,
386// bounds: Bounds<Pixels>,
387// element_state: &mut Self::State,
388// cx: &mut WindowContext,
389// ) {
390// todo!()
391// }
392// }
393
394// impl<V: 'static, E: 'static + Element> RenderOnce for DrawableElement<V, E> {
395// type Element = Self;
396
397// fn element_id(&self) -> Option<ElementId> {
398// self.element.as_ref()?.element_id()
399// }
400
401// fn render_once(self) -> Self::Element {
402// self
403// }
404// }
405
406impl<E> ElementObject for Option<DrawableElement<E>>
407where
408 E: Element,
409 E::State: 'static,
410{
411 fn element_id(&self) -> Option<ElementId> {
412 self.as_ref().unwrap().element_id()
413 }
414
415 fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
416 DrawableElement::layout(self.as_mut().unwrap(), cx)
417 }
418
419 fn paint(&mut self, cx: &mut WindowContext) {
420 DrawableElement::paint(self.take().unwrap(), cx);
421 }
422
423 fn measure(
424 &mut self,
425 available_space: Size<AvailableSpace>,
426 cx: &mut WindowContext,
427 ) -> Size<Pixels> {
428 DrawableElement::measure(self.as_mut().unwrap(), available_space, cx)
429 }
430
431 fn draw(
432 &mut self,
433 origin: Point<Pixels>,
434 available_space: Size<AvailableSpace>,
435 cx: &mut WindowContext,
436 ) {
437 DrawableElement::draw(self.take().unwrap(), origin, available_space, cx);
438 }
439}
440
441pub struct AnyElement(Box<dyn ElementObject>);
442
443impl AnyElement {
444 pub fn new<E>(element: E) -> Self
445 where
446 E: 'static + Element,
447 E::State: Any,
448 {
449 AnyElement(Box::new(Some(DrawableElement::new(element))) as Box<dyn ElementObject>)
450 }
451
452 pub fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
453 self.0.layout(cx)
454 }
455
456 pub fn paint(mut self, cx: &mut WindowContext) {
457 self.0.paint(cx)
458 }
459
460 /// Initializes this element and performs layout within the given available space to determine its size.
461 pub fn measure(
462 &mut self,
463 available_space: Size<AvailableSpace>,
464 cx: &mut WindowContext,
465 ) -> Size<Pixels> {
466 self.0.measure(available_space, cx)
467 }
468
469 /// Initializes this element and performs layout in the available space, then paints it at the given origin.
470 pub fn draw(
471 mut self,
472 origin: Point<Pixels>,
473 available_space: Size<AvailableSpace>,
474 cx: &mut WindowContext,
475 ) {
476 self.0.draw(origin, available_space, cx)
477 }
478
479 /// Converts this `AnyElement` into a trait object that can be stored and manipulated.
480 pub fn into_any(self) -> AnyElement {
481 AnyElement::new(self)
482 }
483
484 pub fn inner_id(&self) -> Option<ElementId> {
485 self.0.element_id()
486 }
487}
488
489impl Element for AnyElement {
490 type State = ();
491
492 fn layout(
493 &mut self,
494 _: Option<Self::State>,
495 cx: &mut WindowContext,
496 ) -> (LayoutId, Self::State) {
497 let layout_id = self.layout(cx);
498 (layout_id, ())
499 }
500
501 fn paint(self, _: Bounds<Pixels>, _: &mut Self::State, cx: &mut WindowContext) {
502 self.paint(cx);
503 }
504}
505
506impl IntoElement for AnyElement {
507 type Element = Self;
508
509 fn element_id(&self) -> Option<ElementId> {
510 None
511 }
512
513 fn into_element(self) -> Self::Element {
514 self
515 }
516}
517
518// impl<V, E, F> Element for Option<F>
519// where
520// V: 'static,
521// E: Element,
522// F: FnOnce(&mut V, &mut WindowContext<'_, V>) -> E + 'static,
523// {
524// type State = Option<AnyElement>;
525
526// fn element_id(&self) -> Option<ElementId> {
527// None
528// }
529
530// fn layout(
531// &mut self,
532// _: Option<Self::State>,
533// cx: &mut WindowContext,
534// ) -> (LayoutId, Self::State) {
535// let render = self.take().unwrap();
536// let mut element = (render)(view_state, cx).into_any();
537// let layout_id = element.layout(view_state, cx);
538// (layout_id, Some(element))
539// }
540
541// fn paint(
542// self,
543// _bounds: Bounds<Pixels>,
544// rendered_element: &mut Self::State,
545// cx: &mut WindowContext,
546// ) {
547// rendered_element.take().unwrap().paint(view_state, cx);
548// }
549// }
550
551// impl<V, E, F> RenderOnce for Option<F>
552// where
553// V: 'static,
554// E: Element,
555// F: FnOnce(&mut V, &mut WindowContext) -> E + 'static,
556// {
557// type Element = Self;
558
559// fn render(self) -> Self::Element {
560// self
561// }
562// }