hook.rs

 1use std::ops::Range;
 2
 3use crate::{
 4    geometry::{rect::RectF, vector::Vector2F},
 5    json::json,
 6    AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, View,
 7    ViewContext,
 8};
 9
10pub struct Hook<V: View> {
11    child: AnyElement<V>,
12    after_layout: Option<Box<dyn FnMut(Vector2F, &mut ViewContext<V>)>>,
13}
14
15impl<V: View> Hook<V> {
16    pub fn new(child: impl Element<V>) -> Self {
17        Self {
18            child: child.into_any(),
19            after_layout: None,
20        }
21    }
22
23    pub fn on_after_layout(
24        mut self,
25        f: impl 'static + FnMut(Vector2F, &mut ViewContext<V>),
26    ) -> Self {
27        self.after_layout = Some(Box::new(f));
28        self
29    }
30}
31
32impl<V: View> Element<V> for Hook<V> {
33    type LayoutState = ();
34    type PaintState = ();
35
36    fn layout(
37        &mut self,
38        constraint: SizeConstraint,
39        view: &mut V,
40        cx: &mut LayoutContext<V>,
41    ) -> (Vector2F, Self::LayoutState) {
42        let size = self.child.layout(constraint, view, cx);
43        if let Some(handler) = self.after_layout.as_mut() {
44            handler(size, cx);
45        }
46        (size, ())
47    }
48
49    fn paint(
50        &mut self,
51        scene: &mut SceneBuilder,
52        bounds: RectF,
53        visible_bounds: RectF,
54        _: &mut Self::LayoutState,
55        view: &mut V,
56        cx: &mut PaintContext<V>,
57    ) {
58        self.child
59            .paint(scene, bounds.origin(), visible_bounds, view, cx);
60    }
61
62    fn rect_for_text_range(
63        &self,
64        range_utf16: Range<usize>,
65        _: RectF,
66        _: RectF,
67        _: &Self::LayoutState,
68        _: &Self::PaintState,
69        view: &V,
70        cx: &ViewContext<V>,
71    ) -> Option<RectF> {
72        self.child.rect_for_text_range(range_utf16, view, cx)
73    }
74
75    fn debug(
76        &self,
77        _: RectF,
78        _: &Self::LayoutState,
79        _: &Self::PaintState,
80        view: &V,
81        cx: &ViewContext<V>,
82    ) -> serde_json::Value {
83        json!({
84            "type": "Hooks",
85            "child": self.child.debug(view, cx),
86        })
87    }
88}