hook.rs

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