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