Skip to main content

freya_core/style/
shadow.rs

1use std::fmt::Display;
2
3use torin::scaled::Scaled;
4
5use crate::prelude::Color;
6
7/// Whether a [`Shadow`] is cast outside the element or inside it.
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[derive(Default, Clone, Debug, PartialEq)]
10pub enum ShadowPosition {
11    /// Drop shadow cast outside the element. This is the default.
12    #[default]
13    Normal,
14    /// Shadow cast inside the element's bounds.
15    Inset,
16}
17
18/// A shadow cast by an element.
19///
20/// Build it from a `(x, y, blur, spread, color)` tuple, or start from [`Shadow::new`]
21/// and chain the methods you need:
22///
23/// ```
24/// # use freya::prelude::*;
25/// let shadow = Shadow::new()
26///     .x(0.0)
27///     .y(4.0)
28///     .blur(8.0)
29///     .spread(0.0)
30///     .color(Color::BLACK)
31///     .inset();
32/// ```
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34#[derive(Default, Clone, Debug, PartialEq)]
35pub struct Shadow {
36    pub(crate) position: ShadowPosition,
37    pub(crate) x: f32,
38    pub(crate) y: f32,
39    pub(crate) blur: f32,
40    pub(crate) spread: f32,
41    pub color: Color,
42}
43
44impl Display for Shadow {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        f.write_str(&format!(
47            "{:?} {} {} {} {}",
48            self.position, self.x, self.y, self.blur, self.spread
49        ))
50    }
51}
52
53impl<C: Into<Color>> From<(f32, f32, f32, f32, C)> for Shadow {
54    fn from((x, y, blur, spread, color): (f32, f32, f32, f32, C)) -> Self {
55        Self {
56            position: ShadowPosition::default(),
57            x,
58            y,
59            blur,
60            spread,
61            color: color.into(),
62        }
63    }
64}
65
66impl Shadow {
67    /// Create a new [`Shadow`] with default values.
68    pub fn new() -> Self {
69        Self::default()
70    }
71
72    /// Shorthand for [Self::position].
73    pub fn inset(mut self) -> Self {
74        self.position = ShadowPosition::Inset;
75        self
76    }
77
78    /// Shorthand for [Self::position].
79    pub fn normal(mut self) -> Self {
80        self.position = ShadowPosition::Normal;
81        self
82    }
83
84    /// Set whether the shadow is cast outside or inside the element. See [`ShadowPosition`].
85    pub fn position(mut self, position: ShadowPosition) -> Self {
86        self.position = position;
87        self
88    }
89
90    /// Set the horizontal offset of the shadow, in pixels.
91    pub fn x(mut self, x: f32) -> Self {
92        self.x = x;
93        self
94    }
95
96    /// Set the vertical offset of the shadow, in pixels.
97    pub fn y(mut self, y: f32) -> Self {
98        self.y = y;
99        self
100    }
101
102    /// Set the blur radius of the shadow, in pixels.
103    pub fn blur(mut self, blur: f32) -> Self {
104        self.blur = blur;
105        self
106    }
107
108    /// Set how much the shadow expands beyond the element's bounds, in pixels.
109    pub fn spread(mut self, spread: f32) -> Self {
110        self.spread = spread;
111        self
112    }
113
114    /// Set the [`Color`] of the shadow.
115    pub fn color(mut self, color: impl Into<Color>) -> Self {
116        self.color = color.into();
117        self
118    }
119}
120
121impl Scaled for Shadow {
122    fn scale(&mut self, scale_factor: f32) {
123        self.x *= scale_factor;
124        self.y *= scale_factor;
125        self.spread *= scale_factor;
126        self.blur *= scale_factor;
127    }
128}