css_style/
position.rs

1use crate::{calc::Calc, unit::*, Style, StyleUpdater};
2use derive_rich::Rich;
3
4/// ```
5/// use css_style::{Style, unit::px};
6///
7/// Style::default()
8///     .and_position(|conf| {
9///         conf.absolute().top(px(28)).left(px(40))
10///     });
11/// ```
12#[derive(Rich, Clone, Debug, PartialEq, Default)]
13pub struct Position {
14    #[rich(write(rename = position), write(option, rename = try_position), value_fns = {
15        static_ = PositionType::Static,
16        absolute = PositionType::Absolute,
17        fixed = PositionType::Fixed,
18        relative = PositionType::Relative,
19        sticky = PositionType::Sticky,
20        initial = PositionType::Initial,
21        inherit = PositionType::Inherit,
22    })]
23    pub position: Option<PositionType>,
24    #[rich(write, write(option))]
25    pub left: Option<PostionLength>,
26    #[rich(write, write(option))]
27    pub top: Option<PostionLength>,
28    #[rich(write, write(option))]
29    pub right: Option<PostionLength>,
30    #[rich(write, write(option))]
31    pub bottom: Option<PostionLength>,
32    #[rich(write, write(option))]
33    pub z_index: Option<i32>,
34    #[rich(write, write(option))]
35    pub clip: Option<Clip>,
36}
37
38impl Position {
39    pub fn move_top(self) -> Self {
40        self.top(px(0))
41    }
42
43    pub fn move_right(self) -> Self {
44        self.right(px(0))
45    }
46
47    pub fn move_bottom(self) -> Self {
48        self.bottom(px(0))
49    }
50
51    pub fn move_left(self) -> Self {
52        self.left(px(0))
53    }
54
55    pub fn move_top_stretch(self) -> Self {
56        self.move_top().move_left().move_right()
57    }
58
59    pub fn move_right_stretch(self) -> Self {
60        self.move_right().move_top().move_bottom()
61    }
62
63    pub fn move_bottom_stretch(self) -> Self {
64        self.move_bottom().move_left().move_right()
65    }
66
67    pub fn move_left_stretch(self) -> Self {
68        self.move_left().move_top().move_bottom()
69    }
70
71    pub fn move_top_right(self) -> Self {
72        self.move_top().move_right()
73    }
74
75    pub fn move_top_left(self) -> Self {
76        self.move_top().move_left()
77    }
78
79    pub fn move_bottom_right(self) -> Self {
80        self.move_bottom().move_right()
81    }
82
83    pub fn move_bottom_left(self) -> Self {
84        self.move_bottom().move_left()
85    }
86
87    pub fn cover(self) -> Self {
88        self.move_top_right().move_bottom_left()
89    }
90}
91
92impl StyleUpdater for Position {
93    fn update_style(self, style: Style) -> Style {
94        style
95            .try_insert("position", self.position.as_ref())
96            .try_insert("left", self.left.as_ref())
97            .try_insert("top", self.top.as_ref())
98            .try_insert("right", self.right.as_ref())
99            .try_insert("bottom", self.bottom.as_ref())
100            .try_insert("z-index", self.z_index.as_ref())
101            .try_insert("clip", self.clip.as_ref())
102    }
103}
104
105impl<T> From<T> for Position
106where
107    T: Into<PositionType>,
108{
109    fn from(source: T) -> Self {
110        Self {
111            position: Some(source.into()),
112            ..Position::default()
113        }
114    }
115}
116
117#[derive(Clone, Debug, PartialEq, Display, From)]
118pub enum PostionLength {
119    #[display(fmt = "initial")]
120    Initial,
121    #[display(fmt = "inherit")]
122    Inherit,
123    #[display(fmt = "auto")]
124    Auto,
125    #[from]
126    Length(Length),
127    #[from(forward)]
128    Percent(Percent),
129}
130
131impl From<Calc> for PostionLength {
132    fn from(source: Calc) -> Self {
133        PostionLength::Length(source.into())
134    }
135}
136
137#[derive(Clone, Debug, PartialEq, Display, From)]
138pub enum Clip {
139    #[display(fmt = "auto")]
140    Auto,
141    #[display(fmt = "rect({}, {}, {}, {})", top, right, bottom, left)]
142    ShapeRect {
143        top: ClipRectLength,
144        right: ClipRectLength,
145        bottom: ClipRectLength,
146        left: ClipRectLength,
147    },
148    #[display(fmt = "initial")]
149    Initial,
150    #[display(fmt = "inherit")]
151    Inherit,
152}
153
154impl Clip {
155    pub fn rect(
156        top: impl Into<ClipRectLength>,
157        right: impl Into<ClipRectLength>,
158        bottom: impl Into<ClipRectLength>,
159        left: impl Into<ClipRectLength>,
160    ) -> Self {
161        Self::ShapeRect {
162            top: top.into(),
163            right: right.into(),
164            bottom: bottom.into(),
165            left: left.into(),
166        }
167    }
168}
169
170#[derive(Clone, Debug, PartialEq, Display, From)]
171pub enum ClipRectLength {
172    #[display(fmt = "initial")]
173    Initial,
174    #[display(fmt = "inherit")]
175    Inherit,
176    #[display(fmt = "auto")]
177    Auto,
178    #[from]
179    Length(Length),
180    #[from(forward)]
181    Percent(Percent),
182}
183
184impl From<Calc> for ClipRectLength {
185    fn from(source: Calc) -> Self {
186        ClipRectLength::Length(source.into())
187    }
188}
189
190#[derive(Clone, Copy, Debug, PartialEq, Display, From)]
191pub enum PositionType {
192    #[display(fmt = "static")]
193    Static,
194    #[display(fmt = "absolute")]
195    Absolute,
196    #[display(fmt = "fixed")]
197    Fixed,
198    #[display(fmt = "relative")]
199    Relative,
200    #[display(fmt = "sticky")]
201    Sticky,
202    #[display(fmt = "initial")]
203    Initial,
204    #[display(fmt = "inherit")]
205    Inherit,
206}