gpui/elements/
container_query.rs1use refineable::Refineable as _;
8
9use crate::{
10 AnyElement, App, AvailableSpace, Bounds, Element, ElementId, GlobalElementId,
11 InspectorElementId, IntoElement, LayoutId, Pixels, Size, Style, StyleRefinement, Styled,
12 Window, relative,
13};
14
15pub fn container_query<E>(
63 render: impl 'static + FnOnce(Size<Pixels>, &mut Window, &mut App) -> E,
64) -> ContainerQuery
65where
66 E: IntoElement,
67{
68 let mut base_style = StyleRefinement::default();
69 base_style.size.width = Some(relative(1.).into());
70 base_style.size.height = Some(relative(1.).into());
71
72 ContainerQuery {
73 render: Some(Box::new(|size, window, cx| {
74 render(size, window, cx).into_any_element()
75 })),
76 style: base_style,
77 }
78}
79
80pub struct ContainerQuery {
82 render: Option<Box<dyn FnOnce(Size<Pixels>, &mut Window, &mut App) -> AnyElement>>,
83 style: StyleRefinement,
84}
85
86impl Element for ContainerQuery {
87 type RequestLayoutState = ();
88 type PrepaintState = Option<AnyElement>;
89
90 fn id(&self) -> Option<ElementId> {
91 None
92 }
93
94 fn source_location(&self) -> Option<&'static core::panic::Location<'static>> {
95 None
96 }
97
98 fn request_layout(
99 &mut self,
100 _id: Option<&GlobalElementId>,
101 _inspector_id: Option<&InspectorElementId>,
102 window: &mut Window,
103 cx: &mut App,
104 ) -> (LayoutId, Self::RequestLayoutState) {
105 let mut style = Style::default();
106 style.refine(&self.style);
107 let layout_id = window.request_layout(style, [], cx);
108 (layout_id, ())
109 }
110
111 fn prepaint(
112 &mut self,
113 _id: Option<&GlobalElementId>,
114 _inspector_id: Option<&InspectorElementId>,
115 bounds: Bounds<Pixels>,
116 _request_layout: &mut Self::RequestLayoutState,
117 window: &mut Window,
118 cx: &mut App,
119 ) -> Option<AnyElement> {
120 let render = self.render.take()?;
121 let mut child = render(bounds.size, window, cx);
122 child.layout_as_root(bounds.size.map(AvailableSpace::Definite), window, cx);
123 child.prepaint_at(bounds.origin, window, cx);
124 Some(child)
125 }
126
127 fn paint(
128 &mut self,
129 _id: Option<&GlobalElementId>,
130 _inspector_id: Option<&InspectorElementId>,
131 _bounds: Bounds<Pixels>,
132 _request_layout: &mut Self::RequestLayoutState,
133 prepaint: &mut Self::PrepaintState,
134 window: &mut Window,
135 cx: &mut App,
136 ) {
137 if let Some(child) = prepaint {
138 child.paint(window, cx);
139 }
140 }
141}
142
143impl IntoElement for ContainerQuery {
144 type Element = Self;
145
146 fn into_element(self) -> Self::Element {
147 self
148 }
149}
150
151impl Styled for ContainerQuery {
152 fn style(&mut self) -> &mut StyleRefinement {
153 &mut self.style
154 }
155}