align.rs

 1use crate::{
 2    json, AfterLayoutContext, DebugContext, Element, ElementBox, Event, EventContext,
 3    LayoutContext, PaintContext, SizeConstraint,
 4};
 5use json::ToJson;
 6use pathfinder_geometry::vector::{vec2f, Vector2F};
 7use serde_json::json;
 8
 9pub struct Align {
10    child: ElementBox,
11    alignment: Vector2F,
12}
13
14impl Align {
15    pub fn new(child: ElementBox) -> Self {
16        Self {
17            child,
18            alignment: Vector2F::zero(),
19        }
20    }
21
22    pub fn top_center(mut self) -> Self {
23        self.alignment = vec2f(0.0, -1.0);
24        self
25    }
26}
27
28impl Element for Align {
29    type LayoutState = ();
30    type PaintState = ();
31
32    fn layout(
33        &mut self,
34        mut constraint: SizeConstraint,
35        ctx: &mut LayoutContext,
36    ) -> (Vector2F, Self::LayoutState) {
37        let mut size = constraint.max;
38        constraint.min = Vector2F::zero();
39        let child_size = self.child.layout(constraint, ctx);
40        if size.x().is_infinite() {
41            size.set_x(child_size.x());
42        }
43        if size.y().is_infinite() {
44            size.set_y(child_size.y());
45        }
46        (size, ())
47    }
48
49    fn after_layout(
50        &mut self,
51        _: Vector2F,
52        _: &mut Self::LayoutState,
53        ctx: &mut AfterLayoutContext,
54    ) {
55        self.child.after_layout(ctx);
56    }
57
58    fn paint(
59        &mut self,
60        bounds: pathfinder_geometry::rect::RectF,
61        _: &mut Self::LayoutState,
62        ctx: &mut PaintContext,
63    ) -> Self::PaintState {
64        let my_center = bounds.size() / 2.;
65        let my_target = my_center + my_center * self.alignment;
66
67        let child_center = self.child.size() / 2.;
68        let child_target = child_center + child_center * self.alignment;
69
70        self.child
71            .paint(bounds.origin() - (child_target - my_target), ctx);
72    }
73
74    fn dispatch_event(
75        &mut self,
76        event: &Event,
77        _: pathfinder_geometry::rect::RectF,
78        _: &mut Self::LayoutState,
79        _: &mut Self::PaintState,
80        ctx: &mut EventContext,
81    ) -> bool {
82        self.child.dispatch_event(event, ctx)
83    }
84
85    fn debug(
86        &self,
87        bounds: pathfinder_geometry::rect::RectF,
88        _: &Self::LayoutState,
89        _: &Self::PaintState,
90        ctx: &DebugContext,
91    ) -> json::Value {
92        json!({
93            "type": "Align",
94            "bounds": bounds.to_json(),
95            "alignment": self.alignment.to_json(),
96            "child": self.child.debug(ctx),
97        })
98    }
99}