use std::marker::PhantomData; use pathfinder_geometry::{rect::RectF, vector::Vector2F}; use crate::{ AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, View, ViewContext, }; pub trait Component { fn render(self, v: &mut V, cx: &mut ViewContext) -> AnyElement; fn into_element(self) -> ComponentAdapter where Self: Sized, { ComponentAdapter::new(self) } } pub struct ComponentAdapter { component: Option, phantom: PhantomData, } impl ComponentAdapter { pub fn new(e: E) -> Self { Self { component: Some(e), phantom: PhantomData, } } } impl + 'static> Element for ComponentAdapter { type LayoutState = AnyElement; type PaintState = (); fn layout( &mut self, constraint: SizeConstraint, view: &mut V, cx: &mut LayoutContext, ) -> (Vector2F, Self::LayoutState) { let component = self.component.take().unwrap(); let mut element = component.render(view, cx.view_context()); let constraint = element.layout(constraint, view, cx); (constraint, element) } fn paint( &mut self, scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, layout: &mut Self::LayoutState, view: &mut V, cx: &mut PaintContext, ) -> Self::PaintState { layout.paint(scene, bounds.origin(), visible_bounds, view, cx) } fn rect_for_text_range( &self, range_utf16: std::ops::Range, _: RectF, _: RectF, element: &Self::LayoutState, _: &Self::PaintState, view: &V, cx: &ViewContext, ) -> Option { element.rect_for_text_range(range_utf16, view, cx) } fn debug( &self, _: RectF, element: &Self::LayoutState, _: &Self::PaintState, view: &V, cx: &ViewContext, ) -> serde_json::Value { serde_json::json!({ "type": "ComponentAdapter", "child": element.debug(view, cx), }) } }