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, 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}