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}