1use std::ops::Range;
2
3use gpui::{
4 geometry::{
5 rect::RectF,
6 vector::{vec2f, Vector2F},
7 },
8 json::ToJson,
9 serde_json::{self, json},
10 AnyElement, Axis, Element, LayoutContext, SceneBuilder, ViewContext,
11};
12
13use crate::CollabTitlebarItem;
14
15pub(crate) struct FacePile {
16 overlap: f32,
17 faces: Vec<AnyElement<CollabTitlebarItem>>,
18}
19
20impl FacePile {
21 pub fn new(overlap: f32) -> FacePile {
22 FacePile {
23 overlap,
24 faces: Vec::new(),
25 }
26 }
27}
28
29impl Element<CollabTitlebarItem> for FacePile {
30 type LayoutState = ();
31 type PaintState = ();
32
33 fn layout(
34 &mut self,
35 constraint: gpui::SizeConstraint,
36 view: &mut CollabTitlebarItem,
37 cx: &mut LayoutContext<CollabTitlebarItem>,
38 ) -> (Vector2F, Self::LayoutState) {
39 debug_assert!(constraint.max_along(Axis::Horizontal) == f32::INFINITY);
40
41 let mut width = 0.;
42 for face in &mut self.faces {
43 width += face.layout(constraint, view, cx).x();
44 }
45 width -= self.overlap * self.faces.len().saturating_sub(1) as f32;
46
47 (Vector2F::new(width, constraint.max.y()), ())
48 }
49
50 fn paint(
51 &mut self,
52 scene: &mut SceneBuilder,
53 bounds: RectF,
54 visible_bounds: RectF,
55 _layout: &mut Self::LayoutState,
56 view: &mut CollabTitlebarItem,
57 cx: &mut ViewContext<CollabTitlebarItem>,
58 ) -> Self::PaintState {
59 let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
60
61 let origin_y = bounds.upper_right().y();
62 let mut origin_x = bounds.upper_right().x();
63
64 for face in self.faces.iter_mut().rev() {
65 let size = face.size();
66 origin_x -= size.x();
67 scene.paint_layer(None, |scene| {
68 face.paint(scene, vec2f(origin_x, origin_y), visible_bounds, view, cx);
69 });
70 origin_x += self.overlap;
71 }
72
73 ()
74 }
75
76 fn rect_for_text_range(
77 &self,
78 _: Range<usize>,
79 _: RectF,
80 _: RectF,
81 _: &Self::LayoutState,
82 _: &Self::PaintState,
83 _: &CollabTitlebarItem,
84 _: &ViewContext<CollabTitlebarItem>,
85 ) -> Option<RectF> {
86 None
87 }
88
89 fn debug(
90 &self,
91 bounds: RectF,
92 _: &Self::LayoutState,
93 _: &Self::PaintState,
94 _: &CollabTitlebarItem,
95 _: &ViewContext<CollabTitlebarItem>,
96 ) -> serde_json::Value {
97 json!({
98 "type": "FacePile",
99 "bounds": bounds.to_json()
100 })
101 }
102}
103
104impl Extend<AnyElement<CollabTitlebarItem>> for FacePile {
105 fn extend<T: IntoIterator<Item = AnyElement<CollabTitlebarItem>>>(&mut self, children: T) {
106 self.faces.extend(children);
107 }
108}