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/chip.rs
1use crate::{
2 elements::{
3 ConstrainedBox, Container, CrossAxisAlignment, Flex, Icon, MainAxisAlignment, MainAxisSize,
4 ParentElement,
5 },
6 scene::Border,
7 Element,
8};
9 
10use super::{
11 components::{UiComponent, UiComponentStyles},
12 text::Span,
13};
14 
15pub struct Chip {
16 label: String,
17 styles: UiComponentStyles,
18 icon: Option<Icon>,
19 close_button: Option<Box<dyn Element>>,
20}
21 
22impl Chip {
23 pub fn new(label: String, styles: UiComponentStyles) -> Self {
24 Self {
25 label,
26 styles,
27 icon: Default::default(),
28 close_button: Default::default(),
29 }
30 }
31 
32 pub fn with_icon(mut self, icon: Icon) -> Self {
33 self.icon = Some(icon);
34 self
35 }
36 
37 pub fn with_close_button(mut self, close_button: Box<dyn Element>) -> Self {
38 self.close_button = Some(close_button);
39 self
40 }
41 
42 fn styles(&self) -> UiComponentStyles {
43 self.styles
44 }
45}
46 
47impl UiComponent for Chip {
48 type ElementType = Container;
49 fn build(self) -> Container {
50 let styles = self.styles();
51 
52 let mut label_and_button = Flex::row()
53 .with_main_axis_alignment(MainAxisAlignment::SpaceBetween)
54 .with_cross_axis_alignment(CrossAxisAlignment::Center)
55 .with_main_axis_size(MainAxisSize::Min);
56 
57 if let Some(icon) = self.icon {
58 label_and_button.add_child(
59 ConstrainedBox::new(icon.finish())
60 .with_width(styles.font_size.unwrap_or_default())
61 .with_height(styles.font_size.unwrap_or_default())
62 .finish(),
63 );
64 }
65 
66 label_and_button.add_child(
67 Container::new(
68 ConstrainedBox::new(Span::new(self.label, styles).build().finish())
69 .with_max_width(240.)
70 .finish(),
71 )
72 .with_margin_left(5.)
73 .finish(),
74 );
75 
76 if let Some(close_button) = self.close_button {
77 label_and_button.add_child(Container::new(close_button).with_margin_left(10.).finish());
78 }
79 
80 let mut container = Container::new(label_and_button.finish())
81 .with_horizontal_padding(4.)
82 .with_vertical_padding(2.)
83 .with_border(
84 Border::all(styles.border_width.unwrap_or_default())
85 .with_border_fill(styles.border_color.unwrap_or_default()),
86 )
87 .with_corner_radius(styles.border_radius.unwrap_or_default());
88 
89 if let Some(background) = styles.background {
90 container = container.with_background(background);
91 }
92 
93 if let Some(margin) = styles.margin {
94 container = container
95 .with_margin_left(margin.left)
96 .with_margin_top(margin.top)
97 .with_margin_right(margin.right)
98 .with_margin_bottom(margin.bottom);
99 }
100 
101 container
102 }
103 
104 /// Overwrites _some_ styles passed in `style` parameter
105 fn with_style(self, styles: UiComponentStyles) -> Self {
106 Self {
107 styles: self.styles.merge(styles),
108 ..self
109 }
110 }
111}
112