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/ui_components/components.rs
1use crate::{
2 color::ColorU,
3 elements::{Element, Fill},
4 fonts::{FamilyId, Properties, Weight},
5 scene::CornerRadius,
6};
7 
8#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
9pub enum BorderStyle {
10 #[default]
11 None,
12 Solid,
13 Double,
14 Dotted,
15}
16 
17#[derive(Copy, Clone, Debug, Default, PartialEq)]
18pub struct Coords {
19 pub top: f32,
20 pub bottom: f32,
21 pub left: f32,
22 pub right: f32,
23}
24 
25impl Coords {
26 pub fn uniform(val: f32) -> Self {
27 Coords {
28 top: val,
29 bottom: val,
30 left: val,
31 right: val,
32 }
33 }
34 
35 pub fn top(mut self, top: f32) -> Self {
36 self.top = top;
37 self
38 }
39 
40 pub fn bottom(mut self, bottom: f32) -> Self {
41 self.bottom = bottom;
42 self
43 }
44 
45 pub fn left(mut self, left: f32) -> Self {
46 self.left = left;
47 self
48 }
49 
50 pub fn right(mut self, right: f32) -> Self {
51 self.right = right;
52 self
53 }
54}
55 
56#[derive(Copy, Clone, Debug, Default, PartialEq)]
57pub struct UiComponentStyles {
58 pub width: Option<f32>, // TODO should be possible to spec units/equations (eg. 100% - 5px)
59 pub height: Option<f32>,
60 pub position: Option<Coords>,
61 pub background: Option<Fill>,
62 pub foreground: Option<Fill>,
63 pub border_color: Option<Fill>,
64 pub border_width: Option<f32>,
65 pub border_style: Option<BorderStyle>,
66 pub border_radius: Option<CornerRadius>,
67 pub font_family_id: Option<FamilyId>,
68 pub font_size: Option<f32>,
69 pub font_color: Option<ColorU>,
70 pub font_weight: Option<Weight>,
71 // TODO add text_decorations (underline, etc.)
72 pub padding: Option<Coords>,
73 pub margin: Option<Coords>,
74}
75 
76impl UiComponentStyles {
77 /// `merge` combines 2 styles together. Self (usually a default) is overwritten by the styles
78 /// from `style` element (in other words: `style` values has higher precedence than `self`).
79 pub fn merge(&self, style: UiComponentStyles) -> Self {
80 UiComponentStyles {
81 width: style.width.or(self.width),
82 height: style.height.or(self.height),
83 position: style.position.or(self.position),
84 background: style.background.or(self.background),
85 foreground: style.foreground.or(self.foreground),
86 border_color: style.border_color.or(self.border_color),
87 border_width: style.border_width.or(self.border_width),
88 border_style: style.border_style.or(self.border_style),
89 border_radius: style.border_radius.or(self.border_radius),
90 font_family_id: style.font_family_id.or(self.font_family_id),
91 font_size: style.font_size.or(self.font_size),
92 font_color: style.font_color.or(self.font_color),
93 font_weight: style.font_weight.or(self.font_weight),
94 padding: style.padding.or(self.padding),
95 margin: style.margin.or(self.margin),
96 }
97 }
98 pub fn set_width(mut self, width: f32) -> Self {
99 self.width = Some(width);
100 self
101 }
102 pub fn set_height(mut self, height: f32) -> Self {
103 self.height = Some(height);
104 self
105 }
106 pub fn set_position(mut self, position: Coords) -> Self {
107 self.position = Some(position);
108 self
109 }
110 pub fn set_background(mut self, background: Fill) -> Self {
111 self.background = Some(background);
112 self
113 }
114 pub fn set_border_color(mut self, border_color: Fill) -> Self {
115 self.border_color = Some(border_color);
116 self
117 }
118 pub fn set_border_width(mut self, border_width: f32) -> Self {
119 self.border_width = Some(border_width);
120 self
121 }
122 pub fn set_border_style(mut self, border_style: BorderStyle) -> Self {
123 self.border_style = Some(border_style);
124 self
125 }
126 pub fn set_border_radius(mut self, border_radius: CornerRadius) -> Self {
127 self.border_radius = Some(border_radius);
128 self
129 }
130 pub fn set_font_family_id(mut self, font_family_id: FamilyId) -> Self {
131 self.font_family_id = Some(font_family_id);
132 self
133 }
134 pub fn set_font_size(mut self, font_size: f32) -> Self {
135 self.font_size = Some(font_size);
136 self
137 }
138 pub fn set_font_color(mut self, font_color: ColorU) -> Self {
139 self.font_color = Some(font_color);
140 self
141 }
142 pub fn set_font_weight(mut self, font_weight: Weight) -> Self {
143 self.font_weight = Some(font_weight);
144 self
145 }
146 pub fn set_padding(mut self, padding: Coords) -> Self {
147 self.padding = Some(padding);
148 self
149 }
150 pub fn set_margin(mut self, margin: Coords) -> Self {
151 self.margin = Some(margin);
152 self
153 }
154 
155 pub fn font_properties(&self) -> Properties {
156 self.font_weight.map_or_else(Properties::default, |weight| {
157 Properties::default().weight(weight)
158 })
159 }
160}
161 
162pub trait UiComponent {
163 type ElementType: Element;
164 
165 fn build(self) -> Self::ElementType;
166 fn with_style(self, style: UiComponentStyles) -> Self;
167}
168 
169#[cfg(test)]
170#[path = "components_test.rs"]
171mod tests;
172