Seregon/StratoSDK

StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.

Rust/27.3 KB/No license
crates/strato-ui-core/src/elements/constrained_box.rs
StratoSDK / crates / strato-ui-core / src / elements / constrained_box.rs
1use crate::{
2 event::DispatchedEvent,
3 text::{word_boundaries::WordBoundariesPolicy, IsRect, SelectionDirection, SelectionType},
4};
5use pathfinder_geometry::rect::RectF;
6 
7use super::{
8 AfterLayoutContext, AppContext, Element, EventContext, LayoutContext, PaintContext, Point,
9 SelectableElement, Selection, SelectionFragment, SizeConstraint,
10};
11use pathfinder_geometry::vector::Vector2F;
12 
13pub struct ConstrainedBox {
14 child: Box<dyn Element>,
15 constraint: SizeConstraint,
16}
17 
18impl ConstrainedBox {
19 pub fn new(child: Box<dyn Element>) -> Self {
20 Self {
21 child,
22 constraint: SizeConstraint {
23 min: Vector2F::zero(),
24 max: Vector2F::splat(f32::INFINITY),
25 },
26 }
27 }
28 
29 pub fn with_max_width(mut self, max_width: f32) -> Self {
30 self.constraint.max.set_x(max_width);
31 self
32 }
33 
34 pub fn with_min_width(mut self, min_width: f32) -> Self {
35 self.constraint.min.set_x(min_width);
36 self
37 }
38 
39 pub fn with_max_height(mut self, max_height: f32) -> Self {
40 self.constraint.max.set_y(max_height);
41 self
42 }
43 
44 pub fn with_min_height(mut self, min_height: f32) -> Self {
45 self.constraint.min.set_y(min_height);
46 self
47 }
48 
49 pub fn with_height(mut self, height: f32) -> Self {
50 self.constraint.min.set_y(height);
51 self.constraint.max.set_y(height);
52 self
53 }
54 
55 pub fn with_width(mut self, width: f32) -> Self {
56 self.constraint.min.set_x(width);
57 self.constraint.max.set_x(width);
58 self
59 }
60}
61 
62impl Element for ConstrainedBox {
63 fn layout(
64 &mut self,
65 mut constraint: SizeConstraint,
66 ctx: &mut LayoutContext,
67 app: &AppContext,
68 ) -> Vector2F {
69 constraint.min = constraint.min.max(self.constraint.min);
70 constraint.max = constraint.max.min(self.constraint.max);
71 constraint.min = constraint.min.min(constraint.max);
72 
73 self.child.layout(constraint, ctx, app)
74 }
75 
76 fn after_layout(&mut self, ctx: &mut AfterLayoutContext, app: &AppContext) {
77 self.child.after_layout(ctx, app);
78 }
79 
80 fn paint(&mut self, origin: Vector2F, ctx: &mut PaintContext, app: &AppContext) {
81 self.child.paint(origin, ctx, app);
82 }
83 
84 fn dispatch_event(
85 &mut self,
86 event: &DispatchedEvent,
87 ctx: &mut EventContext,
88 app: &AppContext,
89 ) -> bool {
90 self.child.dispatch_event(event, ctx, app)
91 }
92 
93 fn size(&self) -> Option<Vector2F> {
94 self.child.size()
95 }
96 
97 fn origin(&self) -> Option<Point> {
98 self.child.origin()
99 }
100 
101 fn as_selectable_element(&self) -> Option<&dyn SelectableElement> {
102 Some(self as &dyn SelectableElement)
103 }
104 
105 #[cfg(any(test, feature = "test-util"))]
106 fn debug_text_content(&self) -> Option<String> {
107 self.child.debug_text_content()
108 }
109}
110 
111impl SelectableElement for ConstrainedBox {
112 fn get_selection(
113 &self,
114 selection_start: Vector2F,
115 selection_end: Vector2F,
116 is_rect: IsRect,
117 ) -> Option<Vec<SelectionFragment>> {
118 self.child
119 .as_selectable_element()
120 .and_then(|selectable_child| {
121 selectable_child.get_selection(selection_start, selection_end, is_rect)
122 })
123 }
124 
125 fn expand_selection(
126 &self,
127 point: Vector2F,
128 direction: SelectionDirection,
129 unit: SelectionType,
130 word_boundaries_policy: &WordBoundariesPolicy,
131 ) -> Option<Vector2F> {
132 self.child
133 .as_selectable_element()
134 .and_then(|selectable_child| {
135 selectable_child.expand_selection(point, direction, unit, word_boundaries_policy)
136 })
137 }
138 
139 fn is_point_semantically_before(
140 &self,
141 absolute_point: Vector2F,
142 absolute_point_other: Vector2F,
143 ) -> Option<bool> {
144 self.child
145 .as_selectable_element()
146 .and_then(|selectable_child| {
147 selectable_child.is_point_semantically_before(absolute_point, absolute_point_other)
148 })
149 }
150 
151 fn smart_select(
152 &self,
153 absolute_point: Vector2F,
154 smart_select_fn: crate::elements::SmartSelectFn,
155 ) -> Option<(Vector2F, Vector2F)> {
156 self.child
157 .as_selectable_element()
158 .and_then(|selectable_child| {
159 selectable_child.smart_select(absolute_point, smart_select_fn)
160 })
161 }
162 
163 fn calculate_clickable_bounds(&self, current_selection: Option<Selection>) -> Vec<RectF> {
164 self.child
165 .as_selectable_element()
166 .map(|selectable_child| selectable_child.calculate_clickable_bounds(current_selection))
167 .unwrap_or_default()
168 }
169}
170