use gpui::{
AbsoluteLength, AnyElement, App, Bounds, Corners, Element, GlobalElementId, InspectorElementId,
IntoElement, LayoutId, Pixels, Styled, Window, px,
};
use theme::Theme;
pub const MENU_BLUR: f32 = 44.0;
pub const PANEL_BLUR: f32 = 12.0;
pub fn material(corner_radius: f32, blur_radius: f32, child: impl IntoElement) -> Material {
let radius = AbsoluteLength::from(px(corner_radius));
Material {
corners: Corners {
top_left: radius,
top_right: radius,
bottom_right: radius,
bottom_left: radius,
},
blur_radius,
child: child.into_any_element(),
}
}
pub trait Frosted: Styled + IntoElement + Sized {
fn material(mut self, blur_radius: f32) -> Material {
let square = AbsoluteLength::from(px(0.0));
let radii = &self.style().corner_radii;
let corners = Corners {
top_left: radii.top_left.unwrap_or(square),
top_right: radii.top_right.unwrap_or(square),
bottom_right: radii.bottom_right.unwrap_or(square),
bottom_left: radii.bottom_left.unwrap_or(square),
};
Material {
corners,
blur_radius,
child: self.into_any_element(),
}
}
}
impl<E: Styled + IntoElement> Frosted for E {}
pub struct Material {
corners: Corners<AbsoluteLength>,
blur_radius: f32,
child: AnyElement,
}
impl Element for Material {
type RequestLayoutState = ();
type PrepaintState = ();
fn id(&self) -> Option<gpui::ElementId> {
None
}
fn source_location(&self) -> Option<&'static core::panic::Location<'static>> {
None
}
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
window: &mut Window,
cx: &mut App,
) -> (LayoutId, ()) {
(self.child.request_layout(window, cx), ())
}
fn prepaint(
&mut self,
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
_bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
window: &mut Window,
cx: &mut App,
) {
self.child.prepaint(window, cx);
}
fn paint(
&mut self,
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
_prepaint: &mut Self::PrepaintState,
window: &mut Window,
cx: &mut App,
) {
if Theme::of(cx).is_glass() {
let rem = window.rem_size();
let corners = Corners {
top_left: self.corners.top_left.to_pixels(rem),
top_right: self.corners.top_right.to_pixels(rem),
bottom_right: self.corners.bottom_right.to_pixels(rem),
bottom_left: self.corners.bottom_left.to_pixels(rem),
};
window.paint_layer(bounds, |window| {
window.paint_backdrop_blur(bounds, corners, px(self.blur_radius));
self.child.paint(window, cx);
});
} else {
self.child.paint(window, cx);
}
}
}
impl IntoElement for Material {
type Element = Self;
fn into_element(self) -> Self::Element {
self
}
}
pub fn layered(child: impl IntoElement) -> Layered {
Layered {
child: child.into_any_element(),
}
}
pub struct Layered {
child: AnyElement,
}
impl Element for Layered {
type RequestLayoutState = ();
type PrepaintState = ();
fn id(&self) -> Option<gpui::ElementId> {
None
}
fn source_location(&self) -> Option<&'static core::panic::Location<'static>> {
None
}
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
window: &mut Window,
cx: &mut App,
) -> (LayoutId, ()) {
(self.child.request_layout(window, cx), ())
}
fn prepaint(
&mut self,
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
_bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
window: &mut Window,
cx: &mut App,
) {
self.child.prepaint(window, cx);
}
fn paint(
&mut self,
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
bounds: Bounds<Pixels>,
_request_layout: &mut Self::RequestLayoutState,
_prepaint: &mut Self::PrepaintState,
window: &mut Window,
cx: &mut App,
) {
window.paint_layer(bounds, |window| self.child.paint(window, cx));
}
}
impl IntoElement for Layered {
type Element = Self;
fn into_element(self) -> Self::Element {
self
}
}