1use crate::{
2 geometry::{rect::RectF, vector::Vector2F},
3 json, AnyElement, Element, LayoutContext, SceneBuilder, SizeConstraint, View, ViewContext,
4};
5use json::ToJson;
6
7use serde_json::json;
8
9pub struct Align<V: View> {
10 child: AnyElement<V>,
11 alignment: Vector2F,
12}
13
14impl<V: View> 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: View> 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 LayoutContext<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 scene: &mut SceneBuilder,
68 bounds: RectF,
69 visible_bounds: RectF,
70 _: &mut Self::LayoutState,
71 view: &mut V,
72 cx: &mut ViewContext<V>,
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 scene,
82 bounds.origin() - (child_target - my_target),
83 visible_bounds,
84 view,
85 cx,
86 );
87 }
88
89 fn rect_for_text_range(
90 &self,
91 range_utf16: std::ops::Range<usize>,
92 _: RectF,
93 _: RectF,
94 _: &Self::LayoutState,
95 _: &Self::PaintState,
96 view: &V,
97 cx: &ViewContext<V>,
98 ) -> Option<RectF> {
99 self.child.rect_for_text_range(range_utf16, view, cx)
100 }
101
102 fn debug(
103 &self,
104 bounds: pathfinder_geometry::rect::RectF,
105 _: &Self::LayoutState,
106 _: &Self::PaintState,
107 view: &V,
108 cx: &ViewContext<V>,
109 ) -> json::Value {
110 json!({
111 "type": "Align",
112 "bounds": bounds.to_json(),
113 "alignment": self.alignment.to_json(),
114 "child": self.child.debug(view, cx),
115 })
116 }
117}