stack.rs

  1use std::ops::Range;
  2
  3use crate::{
  4    geometry::{rect::RectF, vector::Vector2F},
  5    json::{self, json, ToJson},
  6    AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, ViewContext,
  7};
  8
  9/// Element which renders it's children in a stack on top of each other.
 10/// The first child determines the size of the others.
 11pub struct Stack<V> {
 12    children: Vec<AnyElement<V>>,
 13}
 14
 15impl<V> Default for Stack<V> {
 16    fn default() -> Self {
 17        Self {
 18            children: Vec::new(),
 19        }
 20    }
 21}
 22
 23impl<V> Stack<V> {
 24    pub fn new() -> Self {
 25        Self::default()
 26    }
 27}
 28
 29impl<V: 'static> Element<V> for Stack<V> {
 30    type LayoutState = ();
 31    type PaintState = ();
 32
 33    fn layout(
 34        &mut self,
 35        mut constraint: SizeConstraint,
 36        view: &mut V,
 37        cx: &mut LayoutContext<V>,
 38    ) -> (Vector2F, Self::LayoutState) {
 39        let mut size = constraint.min;
 40        let mut children = self.children.iter_mut();
 41        if let Some(bottom_child) = children.next() {
 42            size = bottom_child.layout(constraint, view, cx);
 43            constraint = SizeConstraint::strict(size);
 44        }
 45
 46        for child in children {
 47            child.layout(constraint, view, cx);
 48        }
 49
 50        (size, ())
 51    }
 52
 53    fn paint(
 54        &mut self,
 55        scene: &mut SceneBuilder,
 56        bounds: RectF,
 57        visible_bounds: RectF,
 58        _: &mut Self::LayoutState,
 59        view: &mut V,
 60        cx: &mut PaintContext<V>,
 61    ) -> Self::PaintState {
 62        for child in &mut self.children {
 63            scene.paint_layer(None, |scene| {
 64                child.paint(scene, bounds.origin(), visible_bounds, view, cx);
 65            });
 66        }
 67    }
 68
 69    fn rect_for_text_range(
 70        &self,
 71        range_utf16: Range<usize>,
 72        _: RectF,
 73        _: RectF,
 74        _: &Self::LayoutState,
 75        _: &Self::PaintState,
 76        view: &V,
 77        cx: &ViewContext<V>,
 78    ) -> Option<RectF> {
 79        self.children
 80            .iter()
 81            .rev()
 82            .find_map(|child| child.rect_for_text_range(range_utf16.clone(), view, cx))
 83    }
 84
 85    fn debug(
 86        &self,
 87        bounds: RectF,
 88        _: &Self::LayoutState,
 89        _: &Self::PaintState,
 90        view: &V,
 91        cx: &ViewContext<V>,
 92    ) -> json::Value {
 93        json!({
 94            "type": "Stack",
 95            "bounds": bounds.to_json(),
 96            "children": self.children.iter().map(|child| child.debug(view, cx)).collect::<Vec<json::Value>>()
 97        })
 98    }
 99}
100
101impl<V> Extend<AnyElement<V>> for Stack<V> {
102    fn extend<T: IntoIterator<Item = AnyElement<V>>>(&mut self, children: T) {
103        self.children.extend(children)
104    }
105}