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#include <optional>
21
22namespace Nui::Attributes
23{
24 namespace Detail
25 {
26 template <typename... T>
28 {
29 std::tuple<::Nui::Detail::ObservedAddReference_t<T>...> observed;
30 };
31 template <>
32 struct StylePropertyEbo<void>
33 {};
34 }
35 template <typename FunctionT, typename... T>
37 {
38 using value_type = std::tuple<::Nui::Detail::ObservedAddReference_t<T>...>;
39
40 FunctionT generator;
41 constexpr static bool isStatic()
42 {
43 return sizeof...(T) == 1 && std::is_same_v<UnpackObserved_t<Nui::Detail::PickFirst_t<T...>>, void>;
44 }
45 constexpr auto operator()() const
46 {
47 return generator();
48 }
49
50 template <typename U>
51 constexpr StylePropertyImpl(FunctionT generator, Observed<U> const& observed)
52 : Detail::StylePropertyEbo<T...>{std::forward_as_tuple(observed)}
53 , generator{std::move(generator)}
54 {}
55 template <typename U>
56 constexpr StylePropertyImpl(FunctionT generator, std::weak_ptr<Observed<U>> observed)
57 : Detail::StylePropertyEbo<T...>{std::make_tuple(std::move(observed))}
58 , generator{std::move(generator)}
59 {}
60 template <typename U>
61 constexpr StylePropertyImpl(FunctionT generator, std::shared_ptr<Observed<U>> observed)
62 : Detail::StylePropertyEbo<T...>{std::make_tuple(std::weak_ptr{observed})}
63 , generator{std::move(generator)}
64 {}
65 constexpr StylePropertyImpl(FunctionT generator, std::nullptr_t)
66 : Detail::StylePropertyEbo<T...>{}
67 , generator{std::move(generator)}
68 {}
69 template <typename GeneratorT>
71 FunctionT generator,
73 : Detail::StylePropertyEbo<T...>{std::move(observed).observedValues()}
74 , generator{std::move(generator)}
75 {}
76 };
77 template <typename FunctionT>
78 StylePropertyImpl(FunctionT generator, std::nullptr_t) -> StylePropertyImpl<FunctionT, void>;
79 template <typename FunctionT, typename T>
81 template <typename FunctionT, typename T>
83 template <typename FunctionT, typename T>
84 StylePropertyImpl(FunctionT generator, std::shared_ptr<Observed<T>>)
86 template <typename FunctionT, typename T>
87 StylePropertyImpl(FunctionT generator, std::weak_ptr<Observed<T>>&&)
89 template <typename FunctionT, typename GeneratorT, typename... ObservedT>
91 -> StylePropertyImpl<FunctionT, ObservedT...>;
92
93 namespace Detail
94 {
95 template <typename T>
97 {
98 constexpr static bool value = true;
99 };
100 template <typename FunctionT>
102 {
103 constexpr static bool value = false;
104 };
105 template <typename Property>
107 {
108 using type = typename Property::value_type;
109 constexpr static auto extract(Property& prop)
110 {
111 return prop.observed;
112 }
113 };
114 template <typename FunctionT>
116 {
117 using type = std::tuple<>;
119 {
120 return nullptr;
121 }
122 };
123
124 template <typename IntegerSequence, typename CurrentIndex, typename... Properties>
126
127 template <unsigned... Indices, typename CurrentIndex, typename Property, typename... Properties>
129 std::integer_sequence<unsigned, Indices...>,
130 CurrentIndex,
131 Property,
132 Properties...>
133 {
134 // TODO: eliminate lift, by transforming this class to an mplex functor concept.
135 using type = mplex::lazy_if_vt<
137 mplex::then_<
138 mplex::lift<BuildObservedPropertyIndexList>,
139 std::integer_sequence<unsigned, Indices..., CurrentIndex::value>,
140 mplex::unsigned_<CurrentIndex::value + 1u>,
141 Properties...>,
142 mplex::else_<
143 mplex::lift<BuildObservedPropertyIndexList>,
144 std::integer_sequence<unsigned, Indices...>,
145 mplex::unsigned_<CurrentIndex::value + 1u>,
146 Properties...>>;
147 };
148
149 template <unsigned... Indices, typename CurrentIndex>
150 struct BuildObservedPropertyIndexList<std::integer_sequence<unsigned, Indices...>, CurrentIndex>
151 {
152 using type = std::integer_sequence<unsigned, Indices...>;
153 };
154
155 template <typename IndexList>
157 template <unsigned... Indices>
158 struct ExtractObservedValuesFromProperties<std::integer_sequence<unsigned, Indices...>>
159 {
160 constexpr static auto apply(auto&& propertyTuple)
161 {
162 return std::tuple_cat(std::get<Indices>(propertyTuple).observed...);
163 }
164 };
165 }
166
168 {
169 char const* name;
170 constexpr StyleProperty(char const* name)
171 : name{name}
172 {}
173 // TODO: optimize following functions:
174 auto operator=(char const* value)
175 {
176 return StylePropertyImpl{
177 [name_ = std::string{name}, value = std::string{value}]() {
178 return name_ + ":" + value;
179 },
180 nullptr};
181 }
182 auto operator=(std::string value)
183 {
184 return StylePropertyImpl{
185 [name_ = std::string{name}, value = std::move(value)]() {
186 return name_ + ":" + value;
187 },
188 nullptr};
189 }
190 auto operator=(Observed<std::string> const& observedValue)
191 {
192 return StylePropertyImpl{
193 [name_ = std::string{name}, &observedValue]() {
194 return name_ + ":" + observedValue.value();
195 },
196 observedValue};
197 }
198 auto operator=(std::weak_ptr<Observed<std::string>>&& observedValue)
199 {
200 return StylePropertyImpl{
201 [name_ = std::string{name}, observedValue = std::weak_ptr{observedValue.lock()}]() {
202 if (auto shared = observedValue.lock(); shared)
203 return name_ + ":" + shared->value();
204 return std::string{};
205 },
206 std::move(observedValue)};
207 }
208 auto operator=(std::shared_ptr<Observed<std::string>> observedValue)
209 {
210 return StylePropertyImpl{
211 [name_ = std::string{name}, observedValue = std::weak_ptr{observedValue}]() {
212 if (auto shared = observedValue.lock(); shared)
213 return name_ + ":" + shared->value();
214 return std::string{};
215 },
216 std::move(observedValue)};
217 }
218 template <typename FunctionT, typename... ArgsT>
220 {
221 return StylePropertyImpl{
222 [name_ = std::string{name}, gen = combinator.generator()]() {
223 return name_ + ":" + gen();
224 },
225 std::move(combinator)};
226 }
227 };
228
229 inline namespace Literals
230 {
231 static constexpr StyleProperty operator""_style(char const* name, std::size_t)
232 {
233 return StyleProperty{name};
234 };
235 }
236
237 namespace Detail
238 {
239 template <bool isStatic, typename... Properties>
240 auto makeStyleGenerator(Properties&&... props)
241 {
242 return [... props = std::forward<Properties>(props)]() {
243 // TODO: better performing version:
244 std::stringstream sstr;
245 [&sstr](auto const& head, auto const&... tail) {
246 using expander = int[];
247 const auto headStr = head();
248 sstr << headStr;
249 (void)expander{0, (sstr << (headStr.empty() ? "" : ";") << tail(), void(), 0)...};
250 }(props...);
251 return sstr.str();
252 };
253 }
254 }
255
256 namespace Detail
257 {
258 template <typename... Properties>
259 constexpr auto stripObserved(Properties&... props)
260 {
262 std::integer_sequence<unsigned>,
263 mplex::unsigned_<0>,
264 Properties...>::type>::apply(std::tie(props...));
265 }
266 }
267
268 template <typename... Properties>
269 class Style
270 {
271 public:
275
276 constexpr Style(Properties&&... props)
277 : observedValues_{stripObserved(props...)}
278 , generateStyle_{makeStyleGenerator<isStatic()>(std::forward<Properties>(props)...)}
279 {}
280
281 constexpr static bool isStatic()
282 {
283 return (Properties::isStatic() && ...);
284 }
285
286 std::string toString() const
287 {
288 return generateStyle_();
289 }
290
291 std::function<std::string()> ejectGenerator() &&
292 {
293 return std::move(generateStyle_);
294 }
295
297 {
298 return std::move(observedValues_);
299 }
300
301 private:
302 ObservedValueList observedValues_;
303 std::function<std::string()> generateStyle_;
304 };
305
306 struct style_
307 {
308 template <typename U>
310 Attribute operator=(U&& val) const
311 {
312 return AttributeFactory{"style"}.operator=(std::forward<U>(val));
313 }
314 template <typename U>
316 Attribute operator=(U& val) const
317 {
318 return AttributeFactory{"style"}.operator=(val);
319 }
320 template <typename... T>
322 {
323 if constexpr (Style<T...>::isStatic())
324 {
325 return AttributeFactory{"style"}.operator=(style.toString());
326 }
327 else
328 {
329 return std::apply(
330 [&style]<typename... ObservedValueTypes>(ObservedValueTypes&&... obs) {
331 return AttributeFactory{"style"}.operator=(
332 ObservedValueCombinator{std::forward<ObservedValueTypes>(obs)...}.generate(
333 std::move(style).ejectGenerator()));
334 },
335 std::move(style).ejectObservedValues());
336 }
337 }
338 } static constexpr style;
339}
Definition attribute.hpp:15
Definition attribute_factory.hpp:240
Definition style.hpp:270
std::string toString() const
Definition style.hpp:286
constexpr Style(Properties &&... props)
Definition style.hpp:276
Nui::Detail::FlatTupleTransform_t< Nui::Detail::TupleFilter_t< Detail::IsDynamicStyleProperty, Properties... >, Detail::StripPropertyObserved > ObservedValueList
Definition style.hpp:274
ObservedValueList ejectObservedValues() &&
Definition style.hpp:296
static constexpr bool isStatic()
Definition style.hpp:281
std::function< std::string()> ejectGenerator() &&
Definition style.hpp:291
ContainedT & value()
Definition observed_value.hpp:372
Definition observed_value_combinator.hpp:108
Definition observed_value_combinator.hpp:159
constexpr ObservedValueCombinatorWithGenerator< RendererType, ObservedValues... > generate(RendererType &&generator)
Definition observed_value_combinator.hpp:167
Definition observed_value.hpp:1283
Definition observed_value.hpp:1534
auto makeStyleGenerator(Properties &&... props)
Definition style.hpp:240
constexpr auto stripObserved(Properties &... props)
Definition style.hpp:259
Definition attribute_factory.hpp:14
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:146
static constexpr bool value
Definition style.hpp:98
static constexpr void * extract(StylePropertyImpl< FunctionT, void > &)
Definition style.hpp:118
static constexpr auto extract(Property &prop)
Definition style.hpp:109
typename Property::value_type type
Definition style.hpp:108
std::tuple<::Nui::Detail::ObservedAddReference_t< T >... > observed
Definition style.hpp:29
Definition style.hpp:37
constexpr StylePropertyImpl(FunctionT generator, std::weak_ptr< Observed< U > > observed)
Definition style.hpp:56
constexpr StylePropertyImpl(FunctionT generator, Observed< U > const &observed)
Definition style.hpp:51
FunctionT generator
Definition style.hpp:40
constexpr StylePropertyImpl(FunctionT generator, std::nullptr_t)
Definition style.hpp:65
constexpr auto operator()() const
Definition style.hpp:45
static constexpr bool isStatic()
Definition style.hpp:41
std::tuple<::Nui::Detail::ObservedAddReference_t< T >... > value_type
Definition style.hpp:38
constexpr StylePropertyImpl(FunctionT generator, ObservedValueCombinatorWithGenerator< GeneratorT, T... > &&observed)
Definition style.hpp:70
constexpr StylePropertyImpl(FunctionT generator, std::shared_ptr< Observed< U > > observed)
Definition style.hpp:61
Definition style.hpp:168
auto operator=(std::weak_ptr< Observed< std::string > > &&observedValue)
Definition style.hpp:198
auto operator=(std::shared_ptr< Observed< std::string > > observedValue)
Definition style.hpp:208
auto operator=(std::string value)
Definition style.hpp:182
auto operator=(char const *value)
Definition style.hpp:174
constexpr StyleProperty(char const *name)
Definition style.hpp:170
auto operator=(Observed< std::string > const &observedValue)
Definition style.hpp:190
auto operator=(ObservedValueCombinatorWithGenerator< FunctionT, ArgsT... > &&combinator)
Definition style.hpp:219
char const * name
Definition style.hpp:169
Definition style.hpp:307
auto operator=(Style< T... > &&style) const
Definition style.hpp:321