1use azul_core::dom::{Dom, IdOrClass, IdOrClass::Class, IdOrClassVec};
26use azul_css::dynamic_selector::{CssPropertyWithConditions, CssPropertyWithConditionsVec};
27use azul_css::{
28 props::{
29 basic::{color::ColorU, *},
30 layout::{LayoutAlignSelf, LayoutFlexGrow, LayoutWidth, LayoutHeight},
31 property::{CssProperty, *},
32 style::{LayoutBorderTopWidth, LayoutBorderBottomWidth, LayoutBorderLeftWidth, LayoutBorderRightWidth, StyleBorderTopStyle, BorderStyle, StyleBorderBottomStyle, StyleBorderLeftStyle, StyleBorderRightStyle, StyleBorderTopColor, StyleBorderBottomColor, StyleBorderLeftColor, StyleBorderRightColor, StyleBorderTopLeftRadius, StyleBorderTopRightRadius, StyleBorderBottomLeftRadius, StyleBorderBottomRightRadius},
33 },
34 AzString,
35};
36
37static SPINNER_CLASS: &[IdOrClass] = &[Class(AzString::from_const_str("__azul-native-spinner"))];
38
39const DEFAULT_SIZE: isize = 24;
41const DEFAULT_TRACK_COLOR: ColorU = ColorU { r: 208, g: 212, b: 217, a: 255 };
43const DEFAULT_ACCENT_COLOR: ColorU = ColorU { r: 13, g: 110, b: 253, a: 255 };
45
46#[derive(Debug, Clone, PartialEq, Eq)]
50#[repr(C)]
51pub struct Spinner {
52 pub size: isize,
54 pub color: ColorU,
56 pub track_color: ColorU,
58 pub spinner_style: CssPropertyWithConditionsVec,
60}
61
62fn build_spinner_style(size: isize, color: ColorU, track_color: ColorU) -> CssPropertyWithConditionsVec {
66 let border_width = (size / 8).max(2);
68 let radius = size / 2;
69 CssPropertyWithConditionsVec::from_vec(alloc::vec![
70 CssPropertyWithConditions::simple(CssProperty::align_self(LayoutAlignSelf::Start)),
72 CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(
73 0,
74 ))),
75 CssPropertyWithConditions::simple(CssProperty::const_width(LayoutWidth::const_px(size))),
76 CssPropertyWithConditions::simple(CssProperty::const_height(LayoutHeight::const_px(size))),
77 CssPropertyWithConditions::simple(CssProperty::const_border_top_width(
79 LayoutBorderTopWidth::const_px(border_width),
80 )),
81 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_width(
82 LayoutBorderBottomWidth::const_px(border_width),
83 )),
84 CssPropertyWithConditions::simple(CssProperty::const_border_left_width(
85 LayoutBorderLeftWidth::const_px(border_width),
86 )),
87 CssPropertyWithConditions::simple(CssProperty::const_border_right_width(
88 LayoutBorderRightWidth::const_px(border_width),
89 )),
90 CssPropertyWithConditions::simple(CssProperty::const_border_top_style(StyleBorderTopStyle {
91 inner: BorderStyle::Solid,
92 })),
93 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_style(
94 StyleBorderBottomStyle {
95 inner: BorderStyle::Solid,
96 },
97 )),
98 CssPropertyWithConditions::simple(CssProperty::const_border_left_style(StyleBorderLeftStyle {
99 inner: BorderStyle::Solid,
100 })),
101 CssPropertyWithConditions::simple(CssProperty::const_border_right_style(
102 StyleBorderRightStyle {
103 inner: BorderStyle::Solid,
104 },
105 )),
106 CssPropertyWithConditions::simple(CssProperty::const_border_top_color(StyleBorderTopColor {
108 inner: color,
109 })),
110 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_color(
111 StyleBorderBottomColor { inner: track_color },
112 )),
113 CssPropertyWithConditions::simple(CssProperty::const_border_left_color(StyleBorderLeftColor {
114 inner: track_color,
115 })),
116 CssPropertyWithConditions::simple(CssProperty::const_border_right_color(
117 StyleBorderRightColor { inner: track_color },
118 )),
119 CssPropertyWithConditions::simple(CssProperty::const_border_top_left_radius(
121 StyleBorderTopLeftRadius::const_px(radius),
122 )),
123 CssPropertyWithConditions::simple(CssProperty::const_border_top_right_radius(
124 StyleBorderTopRightRadius::const_px(radius),
125 )),
126 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_left_radius(
127 StyleBorderBottomLeftRadius::const_px(radius),
128 )),
129 CssPropertyWithConditions::simple(CssProperty::const_border_bottom_right_radius(
130 StyleBorderBottomRightRadius::const_px(radius),
131 )),
132 ])
133}
134
135impl Spinner {
136 #[inline]
138 #[must_use] pub fn create() -> Self {
139 Self::with_size(DEFAULT_SIZE)
140 }
141
142 #[inline]
145 #[must_use] pub fn with_size(size: isize) -> Self {
146 Self {
147 size,
148 color: DEFAULT_ACCENT_COLOR,
149 track_color: DEFAULT_TRACK_COLOR,
150 spinner_style: build_spinner_style(size, DEFAULT_ACCENT_COLOR, DEFAULT_TRACK_COLOR),
151 }
152 }
153
154 #[inline]
156 pub fn set_size(&mut self, size: isize) {
157 self.size = size;
158 self.spinner_style = build_spinner_style(size, self.color, self.track_color);
159 }
160
161 #[inline]
163 #[must_use] pub fn with_spinner_size(mut self, size: isize) -> Self {
164 self.set_size(size);
165 self
166 }
167
168 #[inline]
170 pub fn set_color(&mut self, color: ColorU) {
171 self.color = color;
172 self.spinner_style = build_spinner_style(self.size, color, self.track_color);
173 }
174
175 #[inline]
177 #[must_use] pub fn with_color(mut self, color: ColorU) -> Self {
178 self.set_color(color);
179 self
180 }
181
182 #[inline]
184 pub fn set_track_color(&mut self, track_color: ColorU) {
185 self.track_color = track_color;
186 self.spinner_style = build_spinner_style(self.size, self.color, track_color);
187 }
188
189 #[inline]
191 #[must_use] pub fn with_track_color(mut self, track_color: ColorU) -> Self {
192 self.set_track_color(track_color);
193 self
194 }
195
196 #[inline]
198 #[must_use] pub fn swap_with_default(&mut self) -> Self {
199 let mut s = Self::create();
200 core::mem::swap(&mut s, self);
201 s
202 }
203
204 #[inline]
207 #[must_use] pub fn dom(self) -> Dom {
208 Dom::create_div()
209 .with_ids_and_classes(IdOrClassVec::from_const_slice(SPINNER_CLASS))
210 .with_css_props(self.spinner_style)
211 }
212}
213
214impl Default for Spinner {
215 fn default() -> Self {
216 Self::create()
217 }
218}
219
220impl From<Spinner> for Dom {
221 fn from(s: Spinner) -> Self {
222 s.dom()
223 }
224}