gpui/elements/
container_query.rs1use refineable::Refineable as _;
6
7use crate::{
8 AnyElement, App, AvailableSpace, Bounds, Element, ElementId, GlobalElementId,
9 InspectorElementId, IntoElement, LayoutId, Pixels, Size, Style, StyleRefinement, Styled,
10 Window, relative,
11};
12
13pub fn container_query<E>(
34 render: impl 'static + FnOnce(Size<Pixels>, &mut Window, &mut App) -> E,
35) -> ContainerQuery
36where
37 E: IntoElement,
38{
39 let mut base_style = StyleRefinement::default();
40 base_style.size.width = Some(relative(1.).into());
41 base_style.size.height = Some(relative(1.).into());
42
43 ContainerQuery {
44 render: Some(Box::new(|size, window, cx| {
45 render(size, window, cx).into_any_element()
46 })),
47 style: base_style,
48 }
49}
50
51pub struct ContainerQuery {
53 render: Option<Box<dyn FnOnce(Size<Pixels>, &mut Window, &mut App) -> AnyElement>>,
54 style: StyleRefinement,
55}
56
57impl Element for ContainerQuery {
58 type RequestLayoutState = ();
59 type PrepaintState = Option<AnyElement>;
60
61 fn id(&self) -> Option<ElementId> {
62 None
63 }
64
65 fn source_location(&self) -> Option<&'static core::panic::Location<'static>> {
66 None
67 }
68
69 fn request_layout(
70 &mut self,
71 _id: Option<&GlobalElementId>,
72 _inspector_id: Option<&InspectorElementId>,
73 window: &mut Window,
74 cx: &mut App,
75 ) -> (LayoutId, Self::RequestLayoutState) {
76 let mut style = Style::default();
77 style.refine(&self.style);
78 let layout_id = window.request_layout(style, [], cx);
79 (layout_id, ())
80 }
81
82 fn prepaint(
83 &mut self,
84 _id: Option<&GlobalElementId>,
85 _inspector_id: Option<&InspectorElementId>,
86 bounds: Bounds<Pixels>,
87 _request_layout: &mut Self::RequestLayoutState,
88 window: &mut Window,
89 cx: &mut App,
90 ) -> Option<AnyElement> {
91 let render = self.render.take()?;
92 let mut child = render(bounds.size, window, cx);
93 child.layout_as_root(bounds.size.map(AvailableSpace::Definite), window, cx);
94 child.prepaint_at(bounds.origin, window, cx);
95 Some(child)
96 }
97
98 fn paint(
99 &mut self,
100 _id: Option<&GlobalElementId>,
101 _inspector_id: Option<&InspectorElementId>,
102 _bounds: Bounds<Pixels>,
103 _request_layout: &mut Self::RequestLayoutState,
104 prepaint: &mut Self::PrepaintState,
105 window: &mut Window,
106 cx: &mut App,
107 ) {
108 if let Some(child) = prepaint {
109 child.paint(window, cx);
110 }
111 }
112}
113
114impl IntoElement for ContainerQuery {
115 type Element = Self;
116
117 fn into_element(self) -> Self::Element {
118 self
119 }
120}
121
122impl Styled for ContainerQuery {
123 fn style(&mut self) -> &mut StyleRefinement {
124 &mut self.style
125 }
126}