align.rs

  1use crate::{
  2    geometry::{rect::RectF, vector::Vector2F},
  3    json, DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext,
  4    SizeConstraint,
  5};
  6use json::ToJson;
  7
  8use serde_json::json;
  9
 10pub struct Align {
 11    child: ElementBox,
 12    alignment: Vector2F,
 13}
 14
 15impl Align {
 16    pub fn new(child: ElementBox) -> Self {
 17        Self {
 18            child,
 19            alignment: Vector2F::zero(),
 20        }
 21    }
 22
 23    pub fn top(mut self) -> Self {
 24        self.alignment.set_y(-1.0);
 25        self
 26    }
 27
 28    pub fn bottom(mut self) -> Self {
 29        self.alignment.set_y(1.0);
 30        self
 31    }
 32
 33    pub fn left(mut self) -> Self {
 34        self.alignment.set_x(-1.0);
 35        self
 36    }
 37
 38    pub fn right(mut self) -> Self {
 39        self.alignment.set_x(1.0);
 40        self
 41    }
 42}
 43
 44impl Element for Align {
 45    type LayoutState = ();
 46    type PaintState = ();
 47
 48    fn layout(
 49        &mut self,
 50        mut constraint: SizeConstraint,
 51        cx: &mut LayoutContext,
 52    ) -> (Vector2F, Self::LayoutState) {
 53        let mut size = constraint.max;
 54        constraint.min = Vector2F::zero();
 55        let child_size = self.child.layout(constraint, 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        cx: &mut PaintContext,
 71    ) -> Self::PaintState {
 72        let my_center = bounds.size() / 2.;
 73        let my_target = my_center + my_center * self.alignment;
 74
 75        let child_center = self.child.size() / 2.;
 76        let child_target = child_center + child_center * self.alignment;
 77
 78        self.child.paint(
 79            bounds.origin() - (child_target - my_target),
 80            visible_bounds,
 81            cx,
 82        );
 83    }
 84
 85    fn dispatch_event(
 86        &mut self,
 87        event: &Event,
 88        _: pathfinder_geometry::rect::RectF,
 89        _: &mut Self::LayoutState,
 90        _: &mut Self::PaintState,
 91        cx: &mut EventContext,
 92    ) -> bool {
 93        self.child.dispatch_event(event, cx)
 94    }
 95
 96    fn debug(
 97        &self,
 98        bounds: pathfinder_geometry::rect::RectF,
 99        _: &Self::LayoutState,
100        _: &Self::PaintState,
101        cx: &DebugContext,
102    ) -> json::Value {
103        json!({
104            "type": "Align",
105            "bounds": bounds.to_json(),
106            "alignment": self.alignment.to_json(),
107            "child": self.child.debug(cx),
108        })
109    }
110}