ori_core/style/
mod.rs

1mod attribute;
2mod cache;
3mod loader;
4mod parse;
5mod selector;
6mod stylesheet;
7mod transition;
8
9pub use attribute::*;
10pub use cache::*;
11pub use loader::*;
12pub use selector::*;
13pub use stylesheet::*;
14pub use transition::*;
15
16use deref_derive::{Deref, DerefMut};
17
18use crate::{BoxConstraints, DrawContext, Event, EventContext, LayoutContext, View};
19
20#[derive(Clone, Debug, Default)]
21pub struct Style {
22    pub element: Option<&'static str>,
23    pub classes: StyleClasses,
24    pub attributes: StyleAttributes,
25}
26
27impl Style {
28    pub const fn new(element: &'static str) -> Self {
29        Self {
30            element: Some(element),
31            classes: StyleClasses::new(),
32            attributes: StyleAttributes::new(),
33        }
34    }
35
36    pub fn with_element(mut self, name: &'static str) -> Self {
37        self.element = Some(name);
38        self
39    }
40
41    pub fn with_class(mut self, class: &str) -> Self {
42        let classes = class.split_whitespace().map(StyleClass::from);
43        self.classes.extend(classes);
44        self
45    }
46
47    pub fn with_classes(
48        mut self,
49        classes: impl IntoIterator<Item = impl Into<StyleClass>>,
50    ) -> Self {
51        self.classes.extend(classes.into_iter().map(Into::into));
52        self
53    }
54
55    pub fn with_attr(mut self, key: &str, builder: impl StyleAttributeBuilder) -> Self {
56        let attr = builder.attribute(key);
57        self.attributes.add(attr);
58        self
59    }
60
61    pub fn with_attrs(mut self, attrs: impl IntoIterator<Item = StyleAttribute>) -> Self {
62        self.attributes.extend(attrs);
63        self
64    }
65}
66
67/// A value with associated style [`StyleAttributes`].
68#[derive(Clone, Debug, Default, Deref, DerefMut)]
69pub struct Styled<T> {
70    #[deref]
71    pub value: T,
72    pub classes: StyleClasses,
73    pub attributes: StyleAttributes,
74}
75
76impl<T> Styled<T> {
77    /// Creates a new styled value with no attributes.
78    pub const fn new(value: T) -> Self {
79        Self {
80            value,
81            classes: StyleClasses::new(),
82            attributes: StyleAttributes::new(),
83        }
84    }
85}
86
87impl<T: View> View for Styled<T> {
88    type State = T::State;
89
90    fn build(&self) -> Self::State {
91        self.value.build()
92    }
93
94    fn style(&self) -> Style {
95        self.value
96            .style()
97            .with_classes(self.classes.iter().cloned())
98            .with_attrs(self.attributes.iter().cloned())
99    }
100
101    fn event(&self, state: &mut Self::State, cx: &mut EventContext, event: &Event) {
102        self.value.event(state, cx, event)
103    }
104
105    fn layout(
106        &self,
107        state: &mut Self::State,
108        cx: &mut LayoutContext,
109        bc: BoxConstraints,
110    ) -> glam::Vec2 {
111        self.value.layout(state, cx, bc)
112    }
113
114    fn draw(&self, state: &mut Self::State, cx: &mut DrawContext) {
115        self.value.draw(state, cx)
116    }
117}
118
119/// A trait for adding style attributes to a value.
120pub trait Styleable<T> {
121    /// Converts the `self` into a [`Styled<Self>`](Styled) value.
122    fn styled(self) -> Styled<T>;
123
124    /// Adds a class.
125    fn class(self, class: impl AsRef<str>) -> Styled<T>;
126
127    /// Adds an attribute.
128    fn attr(self, key: &str, builder: impl StyleAttributeBuilder) -> Styled<T>;
129
130    /// Adds an attribute with a transition.
131    fn attr_trans(
132        self,
133        key: &str,
134        value: impl Into<StyleAttributeValue>,
135        transition: impl Into<StyleTransition>,
136    ) -> Styled<T>;
137}
138
139impl<T> Styleable<T> for Styled<T> {
140    fn styled(self) -> Styled<T> {
141        self
142    }
143
144    fn class(mut self, class: impl AsRef<str>) -> Styled<T> {
145        let classes = class.as_ref().split_whitespace().map(StyleClass::from);
146        self.classes.extend(classes);
147        self
148    }
149
150    fn attr(mut self, key: &str, builder: impl StyleAttributeBuilder) -> Styled<T> {
151        self.attributes.add(builder.attribute(key));
152        self
153    }
154
155    fn attr_trans(
156        mut self,
157        key: &str,
158        value: impl Into<StyleAttributeValue>,
159        transition: impl Into<StyleTransition>,
160    ) -> Styled<T> {
161        let attr = StyleAttribute::with_transition(key, value, transition);
162        self.attributes.add(attr);
163        self
164    }
165}
166
167impl<T> Styleable<T> for T {
168    fn styled(self) -> Styled<T> {
169        Styled::new(self)
170    }
171
172    fn class(self, class: impl AsRef<str>) -> Styled<T> {
173        Styled::new(self).class(class)
174    }
175
176    fn attr(self, key: &str, value: impl StyleAttributeBuilder) -> Styled<T> {
177        Styled::new(self).attr(key, value)
178    }
179
180    fn attr_trans(
181        self,
182        key: &str,
183        value: impl Into<StyleAttributeValue>,
184        transition: impl Into<StyleTransition>,
185    ) -> Styled<T> {
186        Styled::new(self).attr_trans(key, value, transition)
187    }
188}