ferroui_base/styling/
selectors.rs1use super::{
2 ChildSelector, DescendantSelector, NestingSelector, NotSelector, NthChildSelector, NthLastChildSelector,
3 OrSelector, PropertyEqualsSelector, Selector, TemplateSelector, TypeNameAndClassSelector,
4};
5use crate::{BoxedValue, FerroProperty, ObjectType, PropertyValue, StyledElement, StyledProperty, TypeInfo, Upcast};
6use std::rc::Rc;
7
8pub struct Selectors;
19
20impl Selectors {
21 pub fn child(previous: Option<Selector>) -> Selector {
23 Selector::new(ChildSelector::new(previous))
24 }
25
26 pub fn class(previous: Option<Selector>, name: &str) -> Selector {
28 if name.trim().is_empty() {
29 panic!("Name may not be empty");
30 }
31
32 if let Some(previous) = &previous {
33 if let Some(tac) = previous.node::<TypeNameAndClassSelector>() {
34 tac.add_class(name);
35 return previous.clone();
36 }
37 }
38
39 Selector::new(TypeNameAndClassSelector::for_class(previous, name))
40 }
41
42 pub fn descendant(previous: Option<Selector>) -> Selector {
44 Selector::new(DescendantSelector::new(previous))
45 }
46
47 pub fn is_type_info(previous: Option<Selector>, type_: &'static TypeInfo) -> Selector {
49 Selector::new(TypeNameAndClassSelector::is(previous, type_))
50 }
51
52 pub fn is<T: ObjectType + Upcast<StyledElement>>() -> Selector {
54 Self::is_type_info(None, T::TYPE)
55 }
56
57 pub fn name(previous: Option<Selector>, name: &str) -> Selector {
59 if name.trim().is_empty() {
60 panic!("Name may not be empty");
61 }
62
63 if let Some(previous) = &previous {
64 if let Some(tac) = previous.node::<TypeNameAndClassSelector>() {
65 tac.set_name(name);
66 return previous.clone();
67 }
68 }
69
70 Selector::new(TypeNameAndClassSelector::for_name(previous, name))
71 }
72
73 pub fn nesting(_previous: Option<Selector>) -> Selector {
76 Selector::new(NestingSelector)
77 }
78
79 pub fn not(previous: Option<Selector>, argument: Selector) -> Selector {
81 Selector::new(NotSelector::new(previous, argument))
82 }
83
84 pub fn not_with(previous: Option<Selector>, argument: impl FnOnce(Option<Selector>) -> Selector) -> Selector {
87 Selector::new(NotSelector::new(previous, argument(None)))
88 }
89
90 pub fn nth_child(previous: Option<Selector>, step: i32, offset: i32) -> Selector {
93 Selector::new(NthChildSelector::new(previous, step, offset))
94 }
95
96 pub fn nth_last_child(previous: Option<Selector>, step: i32, offset: i32) -> Selector {
99 Selector::new(NthLastChildSelector::new(previous, step, offset))
100 }
101
102 pub fn of_type_info(previous: Option<Selector>, type_: &'static TypeInfo) -> Selector {
104 Selector::new(TypeNameAndClassSelector::of_type(previous, type_))
105 }
106
107 pub fn of_type<T: ObjectType + Upcast<StyledElement>>() -> Selector {
109 Self::of_type_info(None, T::TYPE)
110 }
111
112 pub fn or(selectors: impl IntoIterator<Item = Selector>) -> Selector {
114 Selector::new(OrSelector::new(selectors.into_iter().collect()))
115 }
116
117 pub fn property_equals<T: PropertyValue>(
120 previous: Option<Selector>,
121 property: &'static StyledProperty<T>,
122 value: T,
123 ) -> Selector {
124 Selector::new(PropertyEqualsSelector::new(previous, property, Rc::new(value)))
125 }
126
127 pub fn property_equals_untyped(
130 previous: Option<Selector>,
131 property: &'static FerroProperty,
132 value: BoxedValue,
133 ) -> Selector {
134 Selector::new(PropertyEqualsSelector::new(previous, property, value))
135 }
136
137 pub fn template(previous: Option<Selector>) -> Selector {
139 Selector::new(TemplateSelector::new(previous))
140 }
141}
142
143impl Selector {
144 pub fn child(self) -> Selector {
146 Selectors::child(Some(self))
147 }
148
149 pub fn class(self, name: &str) -> Selector {
151 Selectors::class(Some(self), name)
152 }
153
154 pub fn descendant(self) -> Selector {
156 Selectors::descendant(Some(self))
157 }
158
159 pub fn is<T: ObjectType + Upcast<StyledElement>>(self) -> Selector {
162 Selectors::is_type_info(Some(self), T::TYPE)
163 }
164
165 pub fn is_type_info(self, type_: &'static TypeInfo) -> Selector {
168 Selectors::is_type_info(Some(self), type_)
169 }
170
171 pub fn name(self, name: &str) -> Selector {
173 Selectors::name(Some(self), name)
174 }
175
176 pub fn nesting(self) -> Selector {
178 Selectors::nesting(Some(self))
179 }
180
181 pub fn not(self, argument: Selector) -> Selector {
184 Selectors::not(Some(self), argument)
185 }
186
187 pub fn not_with(self, argument: impl FnOnce(Option<Selector>) -> Selector) -> Selector {
190 Selectors::not_with(Some(self), argument)
191 }
192
193 pub fn nth_child(self, step: i32, offset: i32) -> Selector {
196 Selectors::nth_child(Some(self), step, offset)
197 }
198
199 pub fn nth_last_child(self, step: i32, offset: i32) -> Selector {
202 Selectors::nth_last_child(Some(self), step, offset)
203 }
204
205 pub fn of_type<T: ObjectType + Upcast<StyledElement>>(self) -> Selector {
207 Selectors::of_type_info(Some(self), T::TYPE)
208 }
209
210 pub fn of_type_info(self, type_: &'static TypeInfo) -> Selector {
212 Selectors::of_type_info(Some(self), type_)
213 }
214
215 pub fn property_equals<T: PropertyValue>(self, property: &'static StyledProperty<T>, value: T) -> Selector {
218 Selectors::property_equals(Some(self), property, value)
219 }
220
221 pub fn property_equals_untyped(self, property: &'static FerroProperty, value: BoxedValue) -> Selector {
225 Selectors::property_equals_untyped(Some(self), property, value)
226 }
227
228 pub fn template(self) -> Selector {
230 Selectors::template(Some(self))
231 }
232}