Nui
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 
22 namespace 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>
70  constexpr StylePropertyImpl(
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>
101  struct IsDynamicStyleProperty<StylePropertyImpl<FunctionT, void>>
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>
115  struct StripPropertyObserved<StylePropertyImpl<FunctionT, void>>
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>
309  requires(!IsObserved<std::decay_t<U>>)
310  Attribute operator=(U&& val) const
311  {
312  return AttributeFactory{"style"}.operator=(std::forward<U>(val));
313  }
314  template <typename U>
315  requires(IsObserved<std::decay_t<U>>)
316  Attribute operator=(U& val) const
317  {
318  return AttributeFactory{"style"}.operator=(val);
319  }
320  template <typename... T>
321  auto operator=(Style<T...>&& style) const
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:235
Definition: style.hpp:270
std::string toString() const
Definition: style.hpp:286
constexpr static bool isStatic()
Definition: style.hpp:281
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
std::function< std::string()> ejectGenerator() &&
Definition: style.hpp:291
ContainedT const & value() const
Definition: observed_value.hpp:313
Definition: observed_value_combinator.hpp:109
Definition: observed_value_combinator.hpp:160
requires constexpr std::invocable< RendererType > ObservedValueCombinatorWithGenerator< RendererType, ObservedValues... > generate(RendererType &&generator)
Definition: observed_value_combinator.hpp:168
Definition: observed_value.hpp:1202
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
StylePropertyImpl(FunctionT generator, std::nullptr_t) -> StylePropertyImpl< FunctionT, void >
requires(std::is_same_v< T, AttributeFactory >||std::is_same_v< T, PropertyFactory >||std::is_same_v< T, EventFactory >) Detail
Definition: attribute_factory.hpp:583
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:1583
concept IsObserved
Definition: observed_value.hpp:1451
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
constexpr static bool value
Definition: style.hpp:98
constexpr static void * extract(StylePropertyImpl< FunctionT, void > &)
Definition: style.hpp:118
constexpr static 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, Observed< U > const &observed)
Definition: style.hpp:51
FunctionT generator
Definition: style.hpp:40
constexpr static bool isStatic()
Definition: style.hpp:41
constexpr StylePropertyImpl(FunctionT generator, std::nullptr_t)
Definition: style.hpp:65
constexpr auto operator()() const
Definition: style.hpp:45
std::tuple<::Nui::Detail::ObservedAddReference_t< T >... > value_type
Definition: style.hpp:38
constexpr StylePropertyImpl(FunctionT generator, std::weak_ptr< Observed< U >> observed)
Definition: style.hpp:56
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::shared_ptr< Observed< std::string >> observedValue)
Definition: style.hpp:208
auto operator=(std::string value)
Definition: style.hpp:182
auto operator=(std::weak_ptr< Observed< std::string >> &&observedValue)
Definition: style.hpp:198
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