use std::ops::Range; use gpui::{ geometry::{ rect::RectF, vector::{vec2f, Vector2F}, }, json::ToJson, serde_json::{self, json}, AnyElement, Axis, Element, LayoutContext, SceneBuilder, ViewContext, }; use crate::CollabTitlebarItem; pub(crate) struct FacePile { overlap: f32, faces: Vec>, } impl FacePile { pub fn new(overlap: f32) -> FacePile { FacePile { overlap, faces: Vec::new(), } } } impl Element for FacePile { type LayoutState = (); type PaintState = (); fn layout( &mut self, constraint: gpui::SizeConstraint, view: &mut CollabTitlebarItem, cx: &mut LayoutContext, ) -> (Vector2F, Self::LayoutState) { debug_assert!(constraint.max_along(Axis::Horizontal) == f32::INFINITY); let mut width = 0.; for face in &mut self.faces { width += face.layout(constraint, view, cx).x(); } width -= self.overlap * self.faces.len().saturating_sub(1) as f32; (Vector2F::new(width, constraint.max.y()), ()) } fn paint( &mut self, scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _layout: &mut Self::LayoutState, view: &mut CollabTitlebarItem, cx: &mut ViewContext, ) -> Self::PaintState { let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); let origin_y = bounds.upper_right().y(); let mut origin_x = bounds.upper_right().x(); for face in self.faces.iter_mut().rev() { let size = face.size(); origin_x -= size.x(); scene.paint_layer(None, |scene| { face.paint(scene, vec2f(origin_x, origin_y), visible_bounds, view, cx); }); origin_x += self.overlap; } () } fn rect_for_text_range( &self, _: Range, _: RectF, _: RectF, _: &Self::LayoutState, _: &Self::PaintState, _: &CollabTitlebarItem, _: &ViewContext, ) -> Option { None } fn debug( &self, bounds: RectF, _: &Self::LayoutState, _: &Self::PaintState, _: &CollabTitlebarItem, _: &ViewContext, ) -> serde_json::Value { json!({ "type": "FacePile", "bounds": bounds.to_json() }) } } impl Extend> for FacePile { fn extend>>(&mut self, children: T) { self.faces.extend(children); } }