align.rs

  1use crate::{
  2    geometry::{rect::RectF, vector::Vector2F},
  3    json, AnyElement, Element, SizeConstraint, ViewContext,
  4};
  5use json::ToJson;
  6
  7use serde_json::json;
  8
  9pub struct Align<V> {
 10    child: AnyElement<V>,
 11    alignment: Vector2F,
 12}
 13
 14impl<V> Align<V> {
 15    pub fn new(child: AnyElement<V>) -> Self {
 16        Self {
 17            child,
 18            alignment: Vector2F::zero(),
 19        }
 20    }
 21
 22    pub fn top(mut self) -> Self {
 23        self.alignment.set_y(-1.0);
 24        self
 25    }
 26
 27    pub fn bottom(mut self) -> Self {
 28        self.alignment.set_y(1.0);
 29        self
 30    }
 31
 32    pub fn left(mut self) -> Self {
 33        self.alignment.set_x(-1.0);
 34        self
 35    }
 36
 37    pub fn right(mut self) -> Self {
 38        self.alignment.set_x(1.0);
 39        self
 40    }
 41}
 42
 43impl<V: 'static> Element<V> for Align<V> {
 44    type LayoutState = ();
 45    type PaintState = ();
 46
 47    fn layout(
 48        &mut self,
 49        mut constraint: SizeConstraint,
 50        view: &mut V,
 51        cx: &mut ViewContext<V>,
 52    ) -> (Vector2F, Self::LayoutState) {
 53        let mut size = constraint.max;
 54        constraint.min = Vector2F::zero();
 55        let child_size = self.child.layout(constraint, view, cx);
 56        if size.x().is_infinite() {
 57            size.set_x(child_size.x());
 58        }
 59        if size.y().is_infinite() {
 60            size.set_y(child_size.y());
 61        }
 62        (size, ())
 63    }
 64
 65    fn paint(
 66        &mut self,
 67        bounds: RectF,
 68        visible_bounds: RectF,
 69        _: &mut Self::LayoutState,
 70        view: &mut V,
 71        cx: &mut ViewContext<V>,
 72    ) -> Self::PaintState {
 73        let my_center = bounds.size() / 2.;
 74        let my_target = my_center + my_center * self.alignment;
 75
 76        let child_center = self.child.size() / 2.;
 77        let child_target = child_center + child_center * self.alignment;
 78
 79        self.child.paint(
 80            bounds.origin() - (child_target - my_target),
 81            visible_bounds,
 82            view,
 83            cx,
 84        );
 85    }
 86
 87    fn rect_for_text_range(
 88        &self,
 89        range_utf16: std::ops::Range<usize>,
 90        _: RectF,
 91        _: RectF,
 92        _: &Self::LayoutState,
 93        _: &Self::PaintState,
 94        view: &V,
 95        cx: &ViewContext<V>,
 96    ) -> Option<RectF> {
 97        self.child.rect_for_text_range(range_utf16, view, cx)
 98    }
 99
100    fn debug(
101        &self,
102        bounds: pathfinder_geometry::rect::RectF,
103        _: &Self::LayoutState,
104        _: &Self::PaintState,
105        view: &V,
106        cx: &ViewContext<V>,
107    ) -> json::Value {
108        json!({
109            "type": "Align",
110            "bounds": bounds.to_json(),
111            "alignment": self.alignment.to_json(),
112            "child": self.child.debug(view, cx),
113        })
114    }
115}