1use crate::{
2 geometry::{rect::RectF, vector::Vector2F},
3 json, AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint,
4 ViewContext,
5};
6use json::ToJson;
7
8use serde_json::json;
9
10pub struct Align<V> {
11 child: AnyElement<V>,
12 alignment: Vector2F,
13}
14
15impl<V> Align<V> {
16 pub fn new(child: AnyElement<V>) -> 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<V: 'static> Element<V> for Align<V> {
45 type LayoutState = ();
46 type PaintState = ();
47
48 fn layout(
49 &mut self,
50 mut constraint: SizeConstraint,
51 view: &mut V,
52 cx: &mut LayoutContext<V>,
53 ) -> (Vector2F, Self::LayoutState) {
54 let mut size = constraint.max;
55 constraint.min = Vector2F::zero();
56 let child_size = self.child.layout(constraint, view, 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 scene: &mut SceneBuilder,
69 bounds: RectF,
70 visible_bounds: RectF,
71 _: &mut Self::LayoutState,
72 view: &mut V,
73 cx: &mut PaintContext<V>,
74 ) -> Self::PaintState {
75 let my_center = bounds.size() / 2.;
76 let my_target = my_center + my_center * self.alignment;
77
78 let child_center = self.child.size() / 2.;
79 let child_target = child_center + child_center * self.alignment;
80
81 self.child.paint(
82 scene,
83 bounds.origin() - (child_target - my_target),
84 visible_bounds,
85 view,
86 cx,
87 );
88 }
89
90 fn rect_for_text_range(
91 &self,
92 range_utf16: std::ops::Range<usize>,
93 _: RectF,
94 _: RectF,
95 _: &Self::LayoutState,
96 _: &Self::PaintState,
97 view: &V,
98 cx: &ViewContext<V>,
99 ) -> Option<RectF> {
100 self.child.rect_for_text_range(range_utf16, view, cx)
101 }
102
103 fn debug(
104 &self,
105 bounds: pathfinder_geometry::rect::RectF,
106 _: &Self::LayoutState,
107 _: &Self::PaintState,
108 view: &V,
109 cx: &ViewContext<V>,
110 ) -> json::Value {
111 json!({
112 "type": "Align",
113 "bounds": bounds.to_json(),
114 "alignment": self.alignment.to_json(),
115 "child": self.child.debug(view, cx),
116 })
117 }
118}