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