stack.rs

  1use std::ops::Range;
  2
  3use crate::{
  4    geometry::{rect::RectF, vector::Vector2F},
  5    json::{self, json, ToJson},
  6    AnyElement, Element, 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 ViewContext<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        bounds: RectF,
 56        visible_bounds: RectF,
 57        _: &mut Self::LayoutState,
 58        view: &mut V,
 59        cx: &mut ViewContext<V>,
 60    ) -> Self::PaintState {
 61        for child in &mut self.children {
 62            cx.scene().push_layer(None);
 63            child.paint(bounds.origin(), visible_bounds, view, cx);
 64            cx.scene().pop_layer();
 65        }
 66    }
 67
 68    fn rect_for_text_range(
 69        &self,
 70        range_utf16: Range<usize>,
 71        _: RectF,
 72        _: RectF,
 73        _: &Self::LayoutState,
 74        _: &Self::PaintState,
 75        view: &V,
 76        cx: &ViewContext<V>,
 77    ) -> Option<RectF> {
 78        self.children
 79            .iter()
 80            .rev()
 81            .find_map(|child| child.rect_for_text_range(range_utf16.clone(), view, cx))
 82    }
 83
 84    fn debug(
 85        &self,
 86        bounds: RectF,
 87        _: &Self::LayoutState,
 88        _: &Self::PaintState,
 89        view: &V,
 90        cx: &ViewContext<V>,
 91    ) -> json::Value {
 92        json!({
 93            "type": "Stack",
 94            "bounds": bounds.to_json(),
 95            "children": self.children.iter().map(|child| child.debug(view, cx)).collect::<Vec<json::Value>>()
 96        })
 97    }
 98}
 99
100impl<V> Extend<AnyElement<V>> for Stack<V> {
101    fn extend<T: IntoIterator<Item = AnyElement<V>>>(&mut self, children: T) {
102        self.children.extend(children)
103    }
104}