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/rect.rs
1use super::{
2 AfterLayoutContext, AppContext, Element, EventContext, Fill, LayoutContext, PaintContext,
3 Point, SizeConstraint,
4};
5use crate::event::DispatchedEvent;
6pub use crate::scene::Border;
7pub use crate::scene::{CornerRadius, DropShadow};
8use pathfinder_color::ColorU;
9use pathfinder_geometry::{
10 rect::RectF,
11 vector::{vec2f, Vector2F},
12};
13pub struct Rect {
14 background: Fill,
15 drop_shadow: Option<DropShadow>,
16 border: Border,
17 corner_radius: CornerRadius,
18 size: Option<Vector2F>,
19 origin: Option<Point>,
20 #[cfg(debug_assertions)]
21 /// Custom panic location, set with [`Rect::set_location_for_panic_logging`]
22 constructor_location: Option<&'static std::panic::Location<'static>>,
23}
24 
25impl Default for Rect {
26 fn default() -> Self {
27 Self::new()
28 }
29}
30 
31impl Rect {
32 #[cfg_attr(debug_assertions, track_caller)]
33 pub fn new() -> Self {
34 Self {
35 drop_shadow: None,
36 background: Fill::None,
37 border: Border::default(),
38 corner_radius: CornerRadius::default(),
39 size: None,
40 origin: None,
41 #[cfg(debug_assertions)]
42 constructor_location: Some(std::panic::Location::caller()),
43 }
44 }
45 
46 pub fn with_corner_radius(mut self, radius: CornerRadius) -> Self {
47 self.corner_radius = radius;
48 self
49 }
50 
51 pub fn with_background<F>(mut self, fill: F) -> Self
52 where
53 F: Into<Fill>,
54 {
55 self.background = fill.into();
56 self
57 }
58 
59 pub fn with_background_color(mut self, color: ColorU) -> Self {
60 self.background = Fill::Solid(color);
61 self
62 }
63 
64 pub fn with_drop_shadow(mut self, drop_shadow: DropShadow) -> Self {
65 self.drop_shadow = Some(drop_shadow);
66 self
67 }
68 
69 pub fn with_horizontal_background_gradient(
70 mut self,
71 start_color: ColorU,
72 end_color: ColorU,
73 ) -> Self {
74 self.background = Fill::Gradient {
75 start: vec2f(0.0, 0.0),
76 end: vec2f(1.0, 0.0),
77 start_color,
78 end_color,
79 };
80 self
81 }
82 
83 pub fn with_background_gradient(
84 mut self,
85 start: Vector2F,
86 end: Vector2F,
87 start_color: ColorU,
88 end_color: ColorU,
89 ) -> Self {
90 self.background = Fill::Gradient {
91 start,
92 end,
93 start_color,
94 end_color,
95 };
96 self
97 }
98 
99 pub fn with_border(mut self, border: Border) -> Self {
100 self.border = border;
101 self
102 }
103}
104 
105impl Element for Rect {
106 fn layout(
107 &mut self,
108 constraint: SizeConstraint,
109 _ctx: &mut LayoutContext,
110 _app: &AppContext,
111 ) -> Vector2F {
112 let size = constraint.max;
113 self.size = Some(size);
114 size
115 }
116 
117 fn after_layout(&mut self, _ctx: &mut AfterLayoutContext, _app: &AppContext) {}
118 
119 fn paint(&mut self, origin: Vector2F, ctx: &mut PaintContext, _app: &AppContext) {
120 self.origin = Some(Point::from_vec2f(origin, ctx.scene.z_index()));
121 let size = self.size.unwrap();
122 
123 #[cfg(debug_assertions)]
124 ctx.scene
125 .set_location_for_panic_logging(self.constructor_location);
126 
127 let rect = ctx
128 .scene
129 .draw_rect_with_hit_recording(RectF::new(origin, size))
130 .with_background(self.background)
131 .with_border(self.border)
132 .with_corner_radius(self.corner_radius);
133 if let Some(drop_shadow) = self.drop_shadow {
134 rect.with_drop_shadow(drop_shadow);
135 }
136 }
137 
138 fn dispatch_event(
139 &mut self,
140 _event: &DispatchedEvent,
141 _ctx: &mut EventContext,
142 _app: &AppContext,
143 ) -> bool {
144 false
145 }
146 
147 fn size(&self) -> Option<Vector2F> {
148 self.size
149 }
150 
151 fn origin(&self) -> Option<Point> {
152 self.origin
153 }
154 
155 #[cfg_attr(debug_assertions, track_caller)]
156 fn finish(mut self) -> Box<dyn Element>
157 where
158 Self: 'static + Sized,
159 {
160 #[cfg(debug_assertions)]
161 {
162 self.constructor_location = Some(std::panic::Location::caller());
163 }
164 Box::new(self)
165 }
166}
167