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