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