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