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