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 left(mut self) -> Self {
29 self.alignment.set_x(-1.0);
30 self
31 }
32
33 pub fn right(mut self) -> Self {
34 self.alignment.set_x(1.0);
35 self
36 }
37}
38
39impl Element for Align {
40 type LayoutState = ();
41 type PaintState = ();
42
43 fn layout(
44 &mut self,
45 mut constraint: SizeConstraint,
46 cx: &mut LayoutContext,
47 ) -> (Vector2F, Self::LayoutState) {
48 let mut size = constraint.max;
49 constraint.min = Vector2F::zero();
50 let child_size = self.child.layout(constraint, cx);
51 if size.x().is_infinite() {
52 size.set_x(child_size.x());
53 }
54 if size.y().is_infinite() {
55 size.set_y(child_size.y());
56 }
57 (size, ())
58 }
59
60 fn paint(
61 &mut self,
62 bounds: RectF,
63 visible_bounds: RectF,
64 _: &mut Self::LayoutState,
65 cx: &mut PaintContext,
66 ) -> Self::PaintState {
67 let my_center = bounds.size() / 2.;
68 let my_target = my_center + my_center * self.alignment;
69
70 let child_center = self.child.size() / 2.;
71 let child_target = child_center + child_center * self.alignment;
72
73 self.child.paint(
74 bounds.origin() - (child_target - my_target),
75 visible_bounds,
76 cx,
77 );
78 }
79
80 fn dispatch_event(
81 &mut self,
82 event: &Event,
83 _: pathfinder_geometry::rect::RectF,
84 _: &mut Self::LayoutState,
85 _: &mut Self::PaintState,
86 cx: &mut EventContext,
87 ) -> bool {
88 self.child.dispatch_event(event, cx)
89 }
90
91 fn debug(
92 &self,
93 bounds: pathfinder_geometry::rect::RectF,
94 _: &Self::LayoutState,
95 _: &Self::PaintState,
96 cx: &DebugContext,
97 ) -> json::Value {
98 json!({
99 "type": "Align",
100 "bounds": bounds.to_json(),
101 "alignment": self.alignment.to_json(),
102 "child": self.child.debug(cx),
103 })
104 }
105}