component.rs

 1use std::marker::PhantomData;
 2
 3use pathfinder_geometry::{rect::RectF, vector::Vector2F};
 4
 5use crate::{
 6    AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, View,
 7    ViewContext,
 8};
 9
10pub trait Component<V: View> {
11    fn render(self, v: &mut V, cx: &mut ViewContext<V>) -> AnyElement<V>;
12
13    fn into_element(self) -> ComponentAdapter<V, Self>
14    where
15        Self: Sized,
16    {
17        ComponentAdapter::new(self)
18    }
19}
20
21pub struct ComponentAdapter<V, E> {
22    component: Option<E>,
23    phantom: PhantomData<V>,
24}
25
26impl<E, V> ComponentAdapter<V, E> {
27    pub fn new(e: E) -> Self {
28        Self {
29            component: Some(e),
30            phantom: PhantomData,
31        }
32    }
33}
34
35impl<V: View, C: Component<V> + 'static> Element<V> for ComponentAdapter<V, C> {
36    type LayoutState = AnyElement<V>;
37
38    type PaintState = ();
39
40    fn layout(
41        &mut self,
42        constraint: SizeConstraint,
43        view: &mut V,
44        cx: &mut LayoutContext<V>,
45    ) -> (Vector2F, Self::LayoutState) {
46        let component = self.component.take().unwrap();
47        let mut element = component.render(view, cx.view_context());
48        let constraint = element.layout(constraint, view, cx);
49        (constraint, element)
50    }
51
52    fn paint(
53        &mut self,
54        scene: &mut SceneBuilder,
55        bounds: RectF,
56        visible_bounds: RectF,
57        layout: &mut Self::LayoutState,
58        view: &mut V,
59        cx: &mut PaintContext<V>,
60    ) -> Self::PaintState {
61        layout.paint(scene, bounds.origin(), visible_bounds, view, cx)
62    }
63
64    fn rect_for_text_range(
65        &self,
66        range_utf16: std::ops::Range<usize>,
67        _: RectF,
68        _: RectF,
69        element: &Self::LayoutState,
70        _: &Self::PaintState,
71        view: &V,
72        cx: &ViewContext<V>,
73    ) -> Option<RectF> {
74        element.rect_for_text_range(range_utf16, view, cx)
75    }
76
77    fn debug(
78        &self,
79        _: RectF,
80        element: &Self::LayoutState,
81        _: &Self::PaintState,
82        view: &V,
83        cx: &ViewContext<V>,
84    ) -> serde_json::Value {
85        element.debug(view, cx)
86    }
87}