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