1use crate::{
2 geometry::{rect::RectF, vector::Vector2F},
3 json, AnyElement, Element, SizeConstraint, ViewContext,
4};
5use json::ToJson;
6
7use serde_json::json;
8
9pub struct Align<V> {
10 child: AnyElement<V>,
11 alignment: Vector2F,
12}
13
14impl<V> Align<V> {
15 pub fn new(child: AnyElement<V>) -> Self {
16 Self {
17 child,
18 alignment: Vector2F::zero(),
19 }
20 }
21
22 pub fn top(mut self) -> Self {
23 self.alignment.set_y(-1.0);
24 self
25 }
26
27 pub fn bottom(mut self) -> Self {
28 self.alignment.set_y(1.0);
29 self
30 }
31
32 pub fn left(mut self) -> Self {
33 self.alignment.set_x(-1.0);
34 self
35 }
36
37 pub fn right(mut self) -> Self {
38 self.alignment.set_x(1.0);
39 self
40 }
41}
42
43impl<V: 'static> Element<V> for Align<V> {
44 type LayoutState = ();
45 type PaintState = ();
46
47 fn layout(
48 &mut self,
49 mut constraint: SizeConstraint,
50 view: &mut V,
51 cx: &mut ViewContext<V>,
52 ) -> (Vector2F, Self::LayoutState) {
53 let mut size = constraint.max;
54 constraint.min = Vector2F::zero();
55 let child_size = self.child.layout(constraint, view, 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 view: &mut V,
71 cx: &mut ViewContext<V>,
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 view,
83 cx,
84 );
85 }
86
87 fn rect_for_text_range(
88 &self,
89 range_utf16: std::ops::Range<usize>,
90 _: RectF,
91 _: RectF,
92 _: &Self::LayoutState,
93 _: &Self::PaintState,
94 view: &V,
95 cx: &ViewContext<V>,
96 ) -> Option<RectF> {
97 self.child.rect_for_text_range(range_utf16, view, cx)
98 }
99
100 fn debug(
101 &self,
102 bounds: pathfinder_geometry::rect::RectF,
103 _: &Self::LayoutState,
104 _: &Self::PaintState,
105 view: &V,
106 cx: &ViewContext<V>,
107 ) -> json::Value {
108 json!({
109 "type": "Align",
110 "bounds": bounds.to_json(),
111 "alignment": self.alignment.to_json(),
112 "child": self.child.debug(view, cx),
113 })
114 }
115}