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