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