1use gpui::{
15 AbsoluteLength, AnyElement, App, Bounds, Corners, Element, GlobalElementId, InspectorElementId,
16 IntoElement, LayoutId, Pixels, Styled, Window, px,
17};
18
19use theme::Theme;
20
21pub const MENU_BLUR: f32 = 44.0;
25
26pub const PANEL_BLUR: f32 = 12.0;
30
31pub fn material(corner_radius: f32, blur_radius: f32, child: impl IntoElement) -> Material {
36 let radius = AbsoluteLength::from(px(corner_radius));
37 Material {
38 corners: Corners {
39 top_left: radius,
40 top_right: radius,
41 bottom_right: radius,
42 bottom_left: radius,
43 },
44 blur_radius,
45 child: child.into_any_element(),
46 }
47}
48
49pub trait Frosted: Styled + IntoElement + Sized {
55 fn material(mut self, blur_radius: f32) -> Material {
56 let square = AbsoluteLength::from(px(0.0));
57 let radii = &self.style().corner_radii;
58 let corners = Corners {
59 top_left: radii.top_left.unwrap_or(square),
60 top_right: radii.top_right.unwrap_or(square),
61 bottom_right: radii.bottom_right.unwrap_or(square),
62 bottom_left: radii.bottom_left.unwrap_or(square),
63 };
64 Material {
65 corners,
66 blur_radius,
67 child: self.into_any_element(),
68 }
69 }
70}
71
72impl<E: Styled + IntoElement> Frosted for E {}
73
74pub struct Material {
75 corners: Corners<AbsoluteLength>,
78 blur_radius: f32,
79 child: AnyElement,
80}
81
82impl Element for Material {
83 type RequestLayoutState = ();
84 type PrepaintState = ();
85
86 fn id(&self) -> Option<gpui::ElementId> {
87 None
88 }
89
90 fn source_location(&self) -> Option<&'static core::panic::Location<'static>> {
91 None
92 }
93
94 fn request_layout(
95 &mut self,
96 _id: Option<&GlobalElementId>,
97 _inspector_id: Option<&InspectorElementId>,
98 window: &mut Window,
99 cx: &mut App,
100 ) -> (LayoutId, ()) {
101 (self.child.request_layout(window, cx), ())
102 }
103
104 fn prepaint(
105 &mut self,
106 _id: Option<&GlobalElementId>,
107 _inspector_id: Option<&InspectorElementId>,
108 _bounds: Bounds<Pixels>,
109 _request_layout: &mut Self::RequestLayoutState,
110 window: &mut Window,
111 cx: &mut App,
112 ) {
113 self.child.prepaint(window, cx);
114 }
115
116 fn paint(
117 &mut self,
118 _id: Option<&GlobalElementId>,
119 _inspector_id: Option<&InspectorElementId>,
120 bounds: Bounds<Pixels>,
121 _request_layout: &mut Self::RequestLayoutState,
122 _prepaint: &mut Self::PrepaintState,
123 window: &mut Window,
124 cx: &mut App,
125 ) {
126 if Theme::of(cx).is_glass() {
127 let rem = window.rem_size();
128 let corners = Corners {
129 top_left: self.corners.top_left.to_pixels(rem),
130 top_right: self.corners.top_right.to_pixels(rem),
131 bottom_right: self.corners.bottom_right.to_pixels(rem),
132 bottom_left: self.corners.bottom_left.to_pixels(rem),
133 };
134 window.paint_layer(bounds, |window| {
135 window.paint_backdrop_blur(bounds, corners, px(self.blur_radius));
136 self.child.paint(window, cx);
137 });
138 } else {
139 self.child.paint(window, cx);
140 }
141 }
142}
143
144impl IntoElement for Material {
145 type Element = Self;
146
147 fn into_element(self) -> Self::Element {
148 self
149 }
150}
151
152pub fn layered(child: impl IntoElement) -> Layered {
161 Layered {
162 child: child.into_any_element(),
163 }
164}
165
166pub struct Layered {
167 child: AnyElement,
168}
169
170impl Element for Layered {
171 type RequestLayoutState = ();
172 type PrepaintState = ();
173
174 fn id(&self) -> Option<gpui::ElementId> {
175 None
176 }
177
178 fn source_location(&self) -> Option<&'static core::panic::Location<'static>> {
179 None
180 }
181
182 fn request_layout(
183 &mut self,
184 _id: Option<&GlobalElementId>,
185 _inspector_id: Option<&InspectorElementId>,
186 window: &mut Window,
187 cx: &mut App,
188 ) -> (LayoutId, ()) {
189 (self.child.request_layout(window, cx), ())
190 }
191
192 fn prepaint(
193 &mut self,
194 _id: Option<&GlobalElementId>,
195 _inspector_id: Option<&InspectorElementId>,
196 _bounds: Bounds<Pixels>,
197 _request_layout: &mut Self::RequestLayoutState,
198 window: &mut Window,
199 cx: &mut App,
200 ) {
201 self.child.prepaint(window, cx);
202 }
203
204 fn paint(
205 &mut self,
206 _id: Option<&GlobalElementId>,
207 _inspector_id: Option<&InspectorElementId>,
208 bounds: Bounds<Pixels>,
209 _request_layout: &mut Self::RequestLayoutState,
210 _prepaint: &mut Self::PrepaintState,
211 window: &mut Window,
212 cx: &mut App,
213 ) {
214 window.paint_layer(bounds, |window| self.child.paint(window, cx));
215 }
216}
217
218impl IntoElement for Layered {
219 type Element = Self;
220
221 fn into_element(self) -> Self::Element {
222 self
223 }
224}