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}