face_pile.rs

  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}