Nui
Loading...
Searching...
No Matches
style.hpp
Go to the documentation of this file.
1#pragma once
2
8
12
13#include <mplex/control/if.hpp>
14#include <mplex/functional/lift.hpp>
15#include <mplex/fundamental/integral.hpp>
16
17#include <tuple>
18#include <string>
19#include <sstream>
20
21namespace Nui::Attributes
22{
23 namespace Detail
24 {
25 template <typename... T>
27 {
28 std::tuple<::Nui::Detail::ObservedAddReference_t<T>...> observed;
29 };
30 template <>
31 struct StylePropertyEbo<void>
32 {};
33 }
34 template <typename FunctionT, typename... T>
36 {
37 using value_type = std::tuple<::Nui::Detail::ObservedAddReference_t<T>...>;
38
39 FunctionT generator;
40 constexpr static bool isStatic()
41 {
42 return sizeof...(T) == 1 && std::is_same_v<UnpackObserved_t<Nui::Detail::PickFirst_t<T...>>, void>;
43 }
44 constexpr auto operator()() const
45 {
46 return generator();
47 }
48
49 template <typename U>
50 constexpr StylePropertyImpl(FunctionT generator, Observed<U> const& observed)
51 : Detail::StylePropertyEbo<T...>{std::forward_as_tuple(observed)}
52 , generator{std::move(generator)}
53 {}
54 template <typename U>
55 constexpr StylePropertyImpl(FunctionT generator, std::weak_ptr<Observed<U>> observed)
56 : Detail::StylePropertyEbo<T...>{std::make_tuple(std::move(observed))}
57 , generator{std::move(generator)}
58 {}
59 template <typename U>
60 constexpr StylePropertyImpl(FunctionT generator, std::shared_ptr<Observed<U>> observed)
61 : Detail::StylePropertyEbo<T...>{std::make_tuple(std::weak_ptr{observed})}
62 , generator{std::move(generator)}
63 {}
64 constexpr StylePropertyImpl(FunctionT generator, std::nullptr_t)
65 : Detail::StylePropertyEbo<T...>{}
66 , generator{std::move(generator)}
67 {}
68 template <typename GeneratorT>
70 FunctionT generator,
72 : Detail::StylePropertyEbo<T...>{std::move(observed).observedValues()}
73 , generator{std::move(generator)}
74 {}
75 };
76 template <typename FunctionT>
77 StylePropertyImpl(FunctionT generator, std::nullptr_t) -> StylePropertyImpl<FunctionT, void>;
78 template <typename FunctionT, typename T>
80 template <typename FunctionT, typename T>
82 template <typename FunctionT, typename T>
83 StylePropertyImpl(FunctionT generator, std::shared_ptr<Observed<T>>)
85 template <typename FunctionT, typename T>
86 StylePropertyImpl(FunctionT generator, std::weak_ptr<Observed<T>>&&)
88 template <typename FunctionT, typename GeneratorT, typename... ObservedT>
90 -> StylePropertyImpl<FunctionT, ObservedT...>;
91
92 namespace Detail
93 {
94 template <typename T>
96 {
97 constexpr static bool value = true;
98 };
99 template <typename FunctionT>
101 {
102 constexpr static bool value = false;
103 };
104 template <typename Property>
106 {
107 using type = typename Property::value_type;
108 constexpr static auto extract(Property& prop)
109 {
110 return prop.observed;
111 }
112 };
113 template <typename FunctionT>
115 {
116 using type = std::tuple<>;
118 {
119 return nullptr;
120 }
121 };
122
123 template <typename IntegerSequence, typename CurrentIndex, typename... Properties>
125
126 template <unsigned... Indices, typename CurrentIndex, typename Property, typename... Properties>
128 std::integer_sequence<unsigned, Indices...>,
129 CurrentIndex,
130 Property,
131 Properties...>
132 {
133 // TODO: eliminate lift, by transforming this class to an mplex functor concept.
134 using type = mplex::lazy_if_vt<
136 mplex::then_<
137 mplex::lift<BuildObservedPropertyIndexList>,
138 std::integer_sequence<unsigned, Indices..., CurrentIndex::value>,
139 mplex::unsigned_<CurrentIndex::value + 1u>,
140 Properties...>,
141 mplex::else_<
142 mplex::lift<BuildObservedPropertyIndexList>,
143 std::integer_sequence<unsigned, Indices...>,
144 mplex::unsigned_<CurrentIndex::value + 1u>,
145 Properties...>>;
146 };
147
148 template <unsigned... Indices, typename CurrentIndex>
149 struct BuildObservedPropertyIndexList<std::integer_sequence<unsigned, Indices...>, CurrentIndex>
150 {
151 using type = std::integer_sequence<unsigned, Indices...>;
152 };
153
154 template <typename IndexList>
156 template <unsigned... Indices>
157 struct ExtractObservedValuesFromProperties<std::integer_sequence<unsigned, Indices...>>
158 {
159 constexpr static auto apply(auto&& propertyTuple)
160 {
161 return std::tuple_cat(std::get<Indices>(propertyTuple).observed...);
162 }
163 };
164 }
165
167 {
168 char const* name;
169 constexpr explicit StyleProperty(char const* name)
170 : name{name}
171 {}
172
174 StyleProperty& operator=(StyleProperty&&) noexcept = delete;
175 StyleProperty(StyleProperty const&) = default;
176 StyleProperty(StyleProperty&&) noexcept = default;
177 ~StyleProperty() = default;
178
179 // TODO: optimize following functions:
180 // NOLINTNEXTLINE(misc-unconventional-assign-operator, cppcoreguidelines-c-copy-assignment-signature)
181 auto operator=(char const* value) const
182 {
183 return StylePropertyImpl{
184 [name_ = std::string{name}, value = std::string{value}]() {
185 return name_ + ":" + value;
186 },
187 nullptr};
188 }
189 // NOLINTNEXTLINE(misc-unconventional-assign-operator, cppcoreguidelines-c-copy-assignment-signature)
190 auto operator=(std::string value) const
191 {
192 return StylePropertyImpl{
193 [name_ = std::string{name}, value = std::move(value)]() {
194 return name_ + ":" + value;
195 },
196 nullptr};
197 }
198 // NOLINTNEXTLINE(misc-unconventional-assign-operator, cppcoreguidelines-c-copy-assignment-signature)
199 auto operator=(Observed<std::string> const& observedValue) const
200 {
201 return StylePropertyImpl{
202 [name_ = std::string{name}, &observedValue]() {
203 return name_ + ":" + observedValue.value();
204 },
205 observedValue};
206 }
207 // NOLINTNEXTLINE(misc-unconventional-assign-operator, cppcoreguidelines-c-copy-assignment-signature)
208 auto operator=(std::weak_ptr<Observed<std::string>>&& observedValue) const
209 {
210 return StylePropertyImpl{
211 [name_ = std::string{name}, observedValue = std::weak_ptr{observedValue.lock()}]() {
212 if (auto shared = observedValue.lock(); shared)
213 return name_ + ":" + shared->value();
214 return std::string{};
215 },
216 std::move(observedValue)};
217 }
218 // NOLINTNEXTLINE(misc-unconventional-assign-operator, cppcoreguidelines-c-copy-assignment-signature)
219 auto operator=(std::shared_ptr<Observed<std::string>> observedValue) const
220 {
221 return StylePropertyImpl{
222 [name_ = std::string{name}, observedValue = std::weak_ptr{observedValue}]() {
223 if (auto shared = observedValue.lock(); shared)
224 return name_ + ":" + shared->value();
225 return std::string{};
226 },
227 std::move(observedValue)};
228 }
229 template <typename FunctionT, typename... ArgsT>
230 // NOLINTNEXTLINE(misc-unconventional-assign-operator, cppcoreguidelines-c-copy-assignment-signature)
232 {
233 return StylePropertyImpl{
234 [name_ = std::string{name}, gen = combinator.generator()]() {
235 return name_ + ":" + gen();
236 },
237 std::move(combinator)};
238 }
239 };
240
241 inline namespace Literals
242 {
243 static constexpr StyleProperty operator""_style(char const* name, std::size_t)
244 {
245 return StyleProperty{name};
246 };
247 }
248
249 namespace Detail
250 {
251 template <bool isStatic, typename... Properties>
252 auto makeStyleGenerator(Properties&&... props)
253 {
254 return [... props = std::forward<Properties>(props)]() {
255 // TODO: better performing version:
256 std::stringstream sstr;
257 [&sstr](auto const& head, auto const&... tail) {
258 // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
259 using expander = int[];
260 const auto headStr = head();
261 sstr << headStr;
262 (void)expander{0, (sstr << (headStr.empty() ? "" : ";") << tail(), void(), 0)...};
263 }(props...);
264 return sstr.str();
265 };
266 }
267 }
268
269 namespace Detail
270 {
271 template <typename... Properties>
272 constexpr auto stripObserved(Properties&... props)
273 {
275 std::integer_sequence<unsigned>,
276 mplex::unsigned_<0>,
277 Properties...>::type>::apply(std::tie(props...));
278 }
279 }
280
281 template <typename... Properties>
282 class Style
283 {
284 public:
288
289 constexpr explicit Style(Properties&&... props)
290 : observedValues_{stripObserved(props...)}
291 , generateStyle_{makeStyleGenerator<isStatic()>(std::forward<Properties>(props)...)}
292 {}
293
294 constexpr static bool isStatic()
295 {
296 return (Properties::isStatic() && ...);
297 }
298
299 std::string toString() const
300 {
301 return generateStyle_();
302 }
303
304 std::function<std::string()> ejectGenerator() &&
305 {
306 return std::move(generateStyle_);
307 }
308
310 {
311 return std::move(observedValues_);
312 }
313
314 private:
315 ObservedValueList observedValues_;
316 std::function<std::string()> generateStyle_;
317 };
318
319 struct style_
320 {
321 style_& operator=(style_&&) noexcept = delete;
322 style_& operator=(style_ const&) = delete;
323 style_() = default;
324 style_(style_&&) noexcept = default;
325 style_(style_ const&) = default;
326 ~style_() = default;
327
328 template <typename U>
329 requires(!IsObserved<std::decay_t<U>>)
330 // NOLINTNEXTLINE(misc-unconventional-assign-operator, cppcoreguidelines-c-copy-assignment-signature)
331 Attribute operator=(U&& val) const
332 {
333 return AttributeFactory{"style"}.operator=(std::forward<U>(val));
334 }
335 template <typename U>
337 // NOLINTNEXTLINE(misc-unconventional-assign-operator, cppcoreguidelines-c-copy-assignment-signature)
338 Attribute operator=(U& val) const
339 {
340 return AttributeFactory{"style"}.operator=(val);
341 }
342 template <typename... T>
343 // NOLINTNEXTLINE(misc-unconventional-assign-operator, cppcoreguidelines-c-copy-assignment-signature)
345 {
346 if constexpr (Style<T...>::isStatic())
347 {
348 return AttributeFactory{"style"}.operator=(style.toString());
349 }
350 else
351 {
352 return std::apply(
353 [&style]<typename... ObservedValueTypes>(ObservedValueTypes&&... obs) {
354 return AttributeFactory{"style"}.operator=(
355 ObservedValueCombinator{std::forward<ObservedValueTypes>(obs)...}.generate(
356 std::move(style).ejectGenerator()));
357 },
358 std::move(style).ejectObservedValues());
359 }
360 }
361 } static constexpr style;
362}
Definition attribute.hpp:15
Definition attribute_factory.hpp:283
Definition style.hpp:283
std::string toString() const
Definition style.hpp:299
constexpr Style(Properties &&... props)
Definition style.hpp:289
Nui::Detail::FlatTupleTransform_t< Nui::Detail::TupleFilter_t< Detail::IsDynamicStyleProperty, Properties... >, Detail::StripPropertyObserved > ObservedValueList
Definition style.hpp:287
ObservedValueList ejectObservedValues() &&
Definition style.hpp:309
static constexpr bool isStatic()
Definition style.hpp:294
std::function< std::string()> ejectGenerator() &&
Definition style.hpp:304
ContainedT & value()
Definition observed_value.hpp:372
Definition observed_value_combinator.hpp:108
Definition observed_value_combinator.hpp:161
constexpr ObservedValueCombinatorWithGenerator< std::decay_t< RendererType >, ObservedValues... > generate(RendererType &&generator)
Definition observed_value_combinator.hpp:169
Definition observed_value.hpp:1283
Definition observed_value.hpp:1534
auto makeStyleGenerator(Properties &&... props)
Definition style.hpp:252
constexpr auto stripObserved(Properties &... props)
Definition style.hpp:272
Definition attribute_factory.hpp:20
struct Nui::Attributes::style_ style
typename TupleFilter< Predicate, T... >::type TupleFilter_t
Definition tuple_filter.hpp:27
typename PickFirst< Ts... >::type PickFirst_t
Definition pick_first.hpp:22
typename FlatTupleTransform< Tuple, Predicate >::type FlatTupleTransform_t
Definition tuple_transform.hpp:31
typename UnpackObserved< T >::type UnpackObserved_t
Definition observed_value.hpp:1666
emscripten::val val
Definition val.hpp:5
mplex::lazy_if_vt< IsDynamicStyleProperty< Property >::value, mplex::then_< mplex::lift< BuildObservedPropertyIndexList >, std::integer_sequence< unsigned, Indices..., CurrentIndex::value >, mplex::unsigned_< CurrentIndex::value+1u >, Properties... >, mplex::else_< mplex::lift< BuildObservedPropertyIndexList >, std::integer_sequence< unsigned, Indices... >, mplex::unsigned_< CurrentIndex::value+1u >, Properties... > > type
Definition style.hpp:145
static constexpr bool value
Definition style.hpp:97
static constexpr void * extract(StylePropertyImpl< FunctionT, void > &)
Definition style.hpp:117
static constexpr auto extract(Property &prop)
Definition style.hpp:108
typename Property::value_type type
Definition style.hpp:107
std::tuple<::Nui::Detail::ObservedAddReference_t< T >... > observed
Definition style.hpp:28
Definition style.hpp:36
constexpr StylePropertyImpl(FunctionT generator, std::weak_ptr< Observed< U > > observed)
Definition style.hpp:55
constexpr StylePropertyImpl(FunctionT generator, Observed< U > const &observed)
Definition style.hpp:50
FunctionT generator
Definition style.hpp:39
constexpr StylePropertyImpl(FunctionT generator, std::nullptr_t)
Definition style.hpp:64
constexpr auto operator()() const
Definition style.hpp:44
static constexpr bool isStatic()
Definition style.hpp:40
std::tuple<::Nui::Detail::ObservedAddReference_t< T >... > value_type
Definition style.hpp:37
constexpr StylePropertyImpl(FunctionT generator, ObservedValueCombinatorWithGenerator< GeneratorT, T... > &&observed)
Definition style.hpp:69
constexpr StylePropertyImpl(FunctionT generator, std::shared_ptr< Observed< U > > observed)
Definition style.hpp:60
Definition style.hpp:167
StyleProperty & operator=(StyleProperty &&) noexcept=delete
auto operator=(ObservedValueCombinatorWithGenerator< FunctionT, ArgsT... > &&combinator) const
Definition style.hpp:231
StyleProperty & operator=(StyleProperty const &)=delete
auto operator=(std::weak_ptr< Observed< std::string > > &&observedValue) const
Definition style.hpp:208
auto operator=(Observed< std::string > const &observedValue) const
Definition style.hpp:199
auto operator=(std::string value) const
Definition style.hpp:190
auto operator=(std::shared_ptr< Observed< std::string > > observedValue) const
Definition style.hpp:219
constexpr StyleProperty(char const *name)
Definition style.hpp:169
char const * name
Definition style.hpp:168
Definition style.hpp:320
style_ & operator=(style_ &&) noexcept=delete
auto operator=(Style< T... > &&style) const
Definition style.hpp:344