Loading...
Searching...
No Matches
Concepts.hpp
1#pragma once
2#include <Process/Dataflow/WidgetInlets.hpp>
3#include <Process/ProcessFlags.hpp>
4#include <Process/ProcessMetadata.hpp>
5
6#include <Dataflow/CurveInlet.hpp>
7#include <Engine/Node/CommonWidgets.hpp>
8
9#include <score/plugins/UuidKey.hpp>
10
11#include <ossia/dataflow/audio_port.hpp>
12#include <ossia/dataflow/port.hpp>
13#include <ossia/dataflow/safe_nodes/tick_policies.hpp>
14
15#include <boost/container/vector.hpp>
16
17#include <avnd/binding/ossia/dynamic_ports.hpp>
18#include <avnd/binding/ossia/qt.hpp>
19#include <avnd/binding/ossia/to_value.hpp>
20#include <avnd/binding/ossia/uuid.hpp>
21#include <avnd/common/concepts_polyfill.hpp>
22#include <avnd/common/struct_reflection.hpp>
23#include <avnd/concepts/audio_port.hpp>
24#include <avnd/concepts/channels.hpp>
25#include <avnd/concepts/curve.hpp>
26#include <avnd/concepts/folder_items.hpp>
27#include <avnd/concepts/gfx.hpp>
28#include <avnd/concepts/midi_port.hpp>
29#include <avnd/concepts/parameter.hpp>
30#include <avnd/introspection/input.hpp>
31#include <avnd/wrappers/metadatas.hpp>
32#include <avnd/wrappers/widgets.hpp>
33
34#include <cmath>
35
36#include <span>
37#include <type_traits>
38
39#define make_uuid(text) score::uuids::string_generator::compute((text))
40
41namespace oscr
42{
47template <typename T>
49 = oscr::has_controller_ports<T> || oscr::has_dynamic_ports<T>
50 || (avnd::controller_setup_port_input_introspection<T>::size > 0);
51
52template <typename Node, typename FieldIndex>
53struct CustomFloatControl;
54
55template <typename BaseInletType, typename Node, typename T, typename FieldIndex>
56struct CustomGenericControl;
57}
58
59template <typename Node, typename FieldIndex>
60struct is_custom_serialized<oscr::CustomFloatControl<Node, FieldIndex>> : std::true_type
61{
62};
63
64template <typename BaseInletType, typename Node, typename T, typename FieldIndex>
65struct is_custom_serialized<
66 oscr::CustomGenericControl<BaseInletType, Node, T, FieldIndex>> : std::true_type
67{
68};
69
70namespace oscr
71{
72
74{
75 using Process::ControlInlet::ControlInlet;
76
78 float min, float max, float init, const QString& name, Id<Process::Port> id,
79 QObject* parent)
80 : ControlInlet{name, id, parent}
81 {
82 displayHandledExplicitly = true;
83 setValue(init);
84 setInit(init);
85 setDomain(ossia::make_domain(min, max));
86 }
87
88 auto getMin() const noexcept { return domain().get().template convert_min<float>(); }
89 auto getMax() const noexcept { return domain().get().template convert_max<float>(); }
90
91 void setupExecution(ossia::inlet& inl, QObject* exec_context) const noexcept override
92 {
93 auto& port = **safe_cast<ossia::value_inlet*>(&inl);
94 port.type = ossia::val_type::FLOAT;
95 port.domain = domain().get();
96 }
97};
98
99template <typename Node, typename FieldIndex>
101{
102 using CustomFloatControlBase::CustomFloatControlBase;
103
104 static key_type static_concreteKey() noexcept
105 {
106 return make_field_uuid<Node>(true, FieldIndex{});
107 }
108 key_type concreteKey() const noexcept override { return static_concreteKey(); }
109
110 void serialize_impl(const VisitorVariant& vis) const noexcept override
111 {
112 score::serialize_dyn(vis, *this);
113 }
114
115 ~CustomFloatControl() = default;
116};
117
118template <typename BaseInletType, typename Node, typename T, typename FieldIndex>
119struct CustomGenericControl : public BaseInletType
120{
121 using BaseInletType::BaseInletType;
122 void setValue(const ossia::value& value) override
123 {
124 if constexpr(requires { T::migrate_value(value); })
125 BaseInletType::setValue(T::migrate_value(value));
126 else
127 BaseInletType::setValue(value);
128 }
129
130 static BaseInletType::key_type static_concreteKey() noexcept
131 {
132 return make_field_uuid<Node>(true, FieldIndex{});
133 }
134 BaseInletType::key_type concreteKey() const noexcept override
135 {
136 return static_concreteKey();
137 }
138
139 void serialize_impl(const VisitorVariant& vis) const noexcept override
140 {
141 score::serialize_dyn(vis, *this);
142 }
143
144 ~CustomGenericControl() = default;
145};
146
147template <typename BaseInletType, typename Node, typename T, typename FieldIndex>
148using ControlTypeToUse = std::conditional_t<
149 avnd::controller_interaction_port<T>,
151}
152template <typename Node, typename FieldIndex>
153struct TSerializer<DataStream, oscr::CustomFloatControl<Node, FieldIndex>>
154{
156 static void readFrom(DataStream::Serializer& s, const model_type& p)
157 {
158 s.read((const Process::ControlInlet&)p);
159 }
160
161 static void writeTo(DataStream::Deserializer& s, model_type& eff) { }
162};
163
164template <typename Node, typename FieldIndex>
165struct TSerializer<JSONObject, oscr::CustomFloatControl<Node, FieldIndex>>
166{
168 static void readFrom(JSONObject::Serializer& s, const model_type& p)
169 {
170 s.read((const Process::ControlInlet&)p);
171 }
172
173 static void writeTo(JSONObject::Deserializer& s, model_type& eff) { }
174};
175
176template <typename BaseInletType, typename Node, typename T, typename FieldIndex>
178 DataStream, oscr::CustomGenericControl<BaseInletType, Node, T, FieldIndex>>
179{
181 static void readFrom(DataStream::Serializer& s, const model_type& p)
182 {
183 s.read((const BaseInletType&)p);
184 }
185
186 static void writeTo(DataStream::Deserializer& s, model_type& eff) { }
187};
188
189template <typename BaseInletType, typename Node, typename T, typename FieldIndex>
191 JSONObject, oscr::CustomGenericControl<BaseInletType, Node, T, FieldIndex>>
192{
194 static void readFrom(JSONObject::Serializer& s, const model_type& p)
195 {
196 s.read((const BaseInletType&)p);
197 }
198
199 static void writeTo(JSONObject::Deserializer& s, model_type& eff) { }
200};
201
202namespace oscr
203{
204
205template <typename Node, typename T, std::size_t N>
206static inline auto
207make_control_in(avnd::field_index<N>, Id<Process::Port>&& id, QObject* parent)
208{
209 using value_type = as_type(T::value);
210 constexpr auto name = avnd::get_name<T>();
211 QString qname = QString::fromUtf8(name.data(), name.size());
212
213 constexpr auto widg = avnd::get_widget<T>();
214
215 // FIXME log normalization & friends
216
217 if constexpr(avnd::curve_port<T>)
218 {
219 return new Dataflow::CurveInlet(id, parent);
220 }
221 else if constexpr(widg.widget == avnd::widget_type::bang)
222 {
223 return new Process::ImpulseButton{qname, id, parent};
224 }
225 else if constexpr(widg.widget == avnd::widget_type::button)
226 {
227 return new Process::Button{qname, id, parent};
228 }
229 else if constexpr(widg.widget == avnd::widget_type::toggle)
230 {
231 static constexpr auto c = avnd::get_range<T>();
232 if constexpr(requires { c.values(); })
233 {
234 return new Process::ChooserToggle{
235 {c.values[0], c.values[1]}, c.init, qname, id, parent};
236 }
237 else
238 {
239 return new Process::Toggle{bool(c.init), qname, id, parent};
240 }
241 }
242 else if constexpr(widg.widget == avnd::widget_type::slider)
243 {
244 static constexpr auto c = avnd::get_range<T>();
245 if constexpr(std::is_integral_v<value_type>)
246 {
247 return new Process::IntSlider{c.min, c.max, c.init, qname, id, parent};
248 }
249 else
250 {
251 if constexpr(avnd::has_mapper<T>)
252 {
253 return new CustomFloatControl<Node, avnd::field_index<N>>{c.min, c.max, c.init,
254 qname, id, parent};
255 }
256 else
257 {
258 return new Process::FloatSlider{c.min, c.max, c.init, qname, id, parent};
259 }
260 }
261 }
262 else if constexpr(widg.widget == avnd::widget_type::log_slider)
263 {
264 static constexpr auto c = avnd::get_range<T>();
265 return new Process::LogFloatSlider{c.min, c.max, c.init, qname, id, parent};
266 }
267 else if constexpr(widg.widget == avnd::widget_type::log_knob)
268 {
269 // FIXME
270 static constexpr auto c = avnd::get_range<T>();
271 return new Process::LogFloatSlider{c.min, c.max, c.init, qname, id, parent};
272 }
273 else if constexpr(widg.widget == avnd::widget_type::time_chooser)
274 {
275 static constexpr auto c = avnd::get_range<T>();
276 return new Process::TimeChooser{c.min, c.max, c.init, qname, id, parent};
277 }
278 else if constexpr(widg.widget == avnd::widget_type::folder)
279 {
280 if constexpr(avnd::has_range<T>) {
281 static constexpr auto c = avnd::get_range<T>();
282#if defined(_MSC_VER)
283 auto init = std::begin(c.init);
284 if constexpr(std::is_same_v<std::decay_t<decltype(init)>, const char*>)
285 return new Process::FolderChooser{QString::fromUtf8(init, std::size(c.init)), qname, id, parent};
286 else
287 return new Process::FolderChooser{QString::fromUtf8(c.init.data(), c.init.size()), qname, id, parent};
288#else
289 return new Process::FolderChooser{
290 QString::fromUtf8(&*std::begin(c.init), std::size(c.init)), qname, id, parent};
291#endif
292 } else {
293 return new Process::FolderChooser{"", qname, id, parent};
294 }
295 }
296 else if constexpr(widg.widget == avnd::widget_type::file)
297 {
298 QString filters;
299 if constexpr(requires { T::filters(); })
300 {
301 constexpr std::string_view f = T::filters();
302 filters = QString::fromUtf8(f.data(), f.size());
303 }
304 return new Process::FileChooser{"", filters, qname, id, parent};
305 }
306 else if constexpr(widg.widget == avnd::widget_type::range_slider)
307 {
308 static constexpr auto c = avnd::get_range<T>();
309 if constexpr(std::is_integral_v<value_type>)
310 {
311 auto [start, end] = c.init;
312 return new Process::IntRangeSlider{c.min, c.max, {(float)start, (float)end},
313 qname, id, parent};
314 }
315 else
316 {
317 auto [start, end] = c.init;
318 return new Process::FloatRangeSlider{c.min, c.max, {(float)start, (float)end},
319 qname, id, parent};
320 }
321 }
322 else if constexpr(widg.widget == avnd::widget_type::range_spinbox)
323 {
324 static constexpr auto c = avnd::get_range<T>();
325 if constexpr(std::is_integral_v<value_type>)
326 {
327 auto [start, end] = c.init;
328 return new Process::IntRangeSpinBox{c.min, c.max, {(float)start, (float)end},
329 qname, id, parent};
330 }
331 else
332 {
333 auto [start, end] = c.init;
334 return new Process::FloatRangeSpinBox{c.min, c.max, {(float)start, (float)end},
335 qname, id, parent};
336 }
337 }
338 else if constexpr(widg.widget == avnd::widget_type::string_list)
339 {
340 auto p
341 = new CustomGenericControl<Process::MultiSlider, Node, T, avnd::field_index<N>>{
342 oscr::to_ossia_value(T{}.value), qname, id, parent};
343 p->setDomain(State::Domain{});
344 return p;
345 }
346 else if constexpr(widg.widget == avnd::widget_type::multi_slider)
347 {
348 std::vector<ossia::value> init;
349 return new Process::MultiSlider{init, qname, id, parent};
350 }
351 else if constexpr(widg.widget == avnd::widget_type::multi_slider_xy)
352 {
353 std::vector<ossia::value> init;
354 return new Process::MultiSliderXY{init, qname, id, parent};
355 }
356 else if constexpr(widg.widget == avnd::widget_type::path_generator_xy)
357 {
358 std::vector<ossia::value> init;
359 return new Process::PathGeneratorXY{init, qname, id, parent};
360 }
361 else if constexpr(widg.widget == avnd::widget_type::spinbox)
362 {
363 static constexpr auto c = avnd::get_range<T>();
364 if constexpr(std::is_integral_v<value_type>)
365 {
366 return new ControlTypeToUse<Process::IntSpinBox, Node, T, avnd::field_index<N>>{
367 c.min, c.max, c.init, qname, id, parent};
368 }
369 else
370 {
371 return new Process::FloatSpinBox{c.min, c.max, c.init, qname, id, parent};
372 }
373 }
374 else if constexpr(widg.widget == avnd::widget_type::knob)
375 {
376 static constexpr auto c = avnd::get_range<T>();
377 if constexpr(std::is_integral_v<value_type>)
378 {
379 // FIXME do a IntKnob
380 return new Process::IntSlider{c.min, c.max, c.init, qname, id, parent};
381 }
382 else
383 {
384 if constexpr(avnd::has_mapper<T>)
385 {
386 return new CustomFloatControl<Node, avnd::field_index<N>>{c.min, c.max, c.init,
387 qname, id, parent};
388 }
389 else
390 {
391 return new Process::FloatKnob{c.min, c.max, c.init, qname, id, parent};
392 }
393 }
394 }
395 else if constexpr(widg.widget == avnd::widget_type::lineedit)
396 {
397 if constexpr(avnd::has_range<T>)
398 {
399 static constexpr auto c = avnd::get_range<T>();
400 if constexpr(avnd::program_parameter<T>)
401 {
402 auto p = new Process::ProgramEdit{c.init.data(), qname, id, parent};
403 p->language = T::language();
404 return p;
405 }
406 else
407 return new ControlTypeToUse<Process::LineEdit, Node, T, avnd::field_index<N>>{
408 c.init.data(), qname, id, parent};
409 }
410 else
411 {
412 if constexpr(avnd::program_parameter<T>)
413 {
414 auto p = new Process::ProgramEdit{"", qname, id, parent};
415 p->language = T::language();
416 return p;
417 }
418 else
419 return new ControlTypeToUse<Process::LineEdit, Node, T, avnd::field_index<N>>{
420 "", qname, id, parent};
421 }
422 }
423 else if constexpr(avnd::folder_items_parameter<T>)
424 {
425 // Folder-backed, string-valued combobox: the value IS the selected file
426 // name, so an object uses it directly like a file-name string. Items are
427 // filled from the sibling folder port at edit time by the model.
428 static constexpr auto c = avnd::get_range<T>();
429 const std::string initv{c.init};
430 std::vector<std::pair<QString, ossia::value>> initAlts;
431 initAlts.emplace_back(QString::fromStdString(initv), initv);
432 auto combo = new Process::ComboBox{
433 std::move(initAlts), ossia::value{initv}, qname, id, parent};
434 combo->folderPortName
435 = QString::fromUtf8(T::folder_port().data(), T::folder_port().size());
436 // extensions(): space-separated suffixes ("wav aif json") -> "*.wav" ...
437 const std::string_view ex = T::extensions();
438 std::size_t pos = 0;
439 while(pos < ex.size())
440 {
441 auto sp = ex.find(' ', pos);
442 if(sp == std::string_view::npos)
443 sp = ex.size();
444 if(sp > pos)
445 {
446 auto suffix = QString::fromUtf8(ex.data() + pos, int(sp - pos));
447 // Both "wav" and ".wav" are natural to write; normalise so neither
448 // turns into the glob "*..wav", which matches nothing.
449 while(suffix.startsWith('.'))
450 suffix.remove(0, 1);
451 if(!suffix.isEmpty())
452 combo->fileExtensions.push_back("*." + suffix);
453 }
454 pos = sp + 1;
455 }
456 return combo;
457 }
458 else if constexpr(widg.widget == avnd::widget_type::combobox)
459 {
460 static constexpr auto c = avnd::get_range<T>();
461 using init_type = std::decay_t<decltype(c.init)>;
462 ossia::value init;
463 if constexpr(std::is_integral_v<init_type> || std::is_enum_v<init_type>)
464 init = static_cast<int>(c.init);
465 else
466 init = c.init;
467 return new Process::ComboBox{
468 to_combobox_range(c.values), std::move(init), qname, id, parent};
469 }
470 else if constexpr(widg.widget == avnd::widget_type::choices)
471 {
472 static constexpr auto c = avnd::get_range<T>();
473 auto enums = avnd::to_enum_range(c.values);
474 static_assert(
475 std::is_integral_v<decltype(c.init)> || std::is_enum_v<decltype(c.init)>);
476 auto init = enums[static_cast<int>(c.init)];
477 std::vector<QString> pixmaps;
478 if constexpr(avnd::has_pixmaps<T>)
479 {
480 for(std::string_view pix : avnd::get_pixmaps<T>())
481 {
482 pixmaps.push_back(QString::fromLatin1(pix.data(), pix.size()));
483 }
484 }
485 return new Process::Enum{
486 std::move(enums), pixmaps, std::move(init), qname, id, parent};
487 }
488 else if constexpr(widg.widget == avnd::widget_type::xy)
489 {
490 static constexpr auto c = avnd::get_range<T>();
491 if constexpr(requires {
492 c.min == 0.f;
493 c.max == 0.f;
494 c.init == 0.f;
495 })
496 {
497 return new Process::XYSlider{
498 {c.min, c.min}, {c.max, c.max}, {c.init, c.init}, qname, id, parent};
499 }
500 else
501 {
502 auto [mx, my] = c.min;
503 auto [Mx, My] = c.max;
504 auto [ix, iy] = c.init;
505 return new Process::XYSlider{{mx, my}, {Mx, My}, {ix, iy}, qname, id, parent};
506 }
507 }
508 else if constexpr(widg.widget == avnd::widget_type::xyz)
509 {
510 static constexpr auto c = avnd::get_range<T>();
511 if constexpr(requires {
512 c.min == 0.f;
513 c.max == 0.f;
514 c.init == 0.f;
515 })
516 {
517 return new Process::XYZSlider{
518 {c.min, c.min, c.min},
519 {c.max, c.max, c.max},
520 {c.init, c.init, c.init},
521 qname,
522 id,
523 parent};
524 }
525 else
526 {
527 auto [mx, my, mz] = c.min;
528 auto [Mx, My, Mz] = c.max;
529 auto [ix, iy, iz] = c.init;
530 return new Process::XYZSlider{{mx, my, mz}, {Mx, My, Mz}, {ix, iy, iz},
531 qname, id, parent};
532 }
533 }
534 else if constexpr(widg.widget == avnd::widget_type::xy_spinbox)
535 {
536 using data_type = std::decay_t<decltype(value_type{}.x)>;
537 static constexpr auto c = avnd::get_range<T>();
538 if constexpr(requires {
539 c.min == 0.f;
540 c.max == 0.f;
541 c.init == 0.f;
542 })
543 {
544 return new Process::XYSpinboxes{
545 {c.min, c.min},
546 {c.max, c.max},
547 {c.init, c.init},
548 std::is_integral_v<data_type>,
549 qname,
550 id,
551 parent};
552 }
553 else
554 {
555 auto [mx, my] = c.min;
556 auto [Mx, My] = c.max;
557 auto [ix, iy] = c.init;
558 return new Process::XYSpinboxes{
559 {mx, my}, {Mx, My}, {ix, iy}, std::is_integral_v<data_type>,
560 qname, id, parent};
561 }
562 }
563 else if constexpr(widg.widget == avnd::widget_type::xyz_spinbox)
564 {
565 static constexpr auto c = avnd::get_range<T>();
566 if constexpr(requires {
567 c.min == 0.f;
568 c.max == 0.f;
569 c.init == 0.f;
570 })
571 {
572 // halp::range only has a scalar init: a port that needs another
573 // default per axis sets it in its constructor.
574 std::array<float, 3> init{c.init, c.init, c.init};
575 if constexpr(std::is_default_constructible_v<T>)
576 {
577 const auto [ix, iy, iz] = T{}.value;
578 init = {float(ix), float(iy), float(iz)};
579 }
580 return new Process::XYZSpinboxes{
581 {c.min, c.min, c.min},
582 {c.max, c.max, c.max},
583 {init[0], init[1], init[2]},
584 false,
585 qname,
586 id,
587 parent};
588 }
589 else
590 {
591 auto [mx, my, mz] = c.min;
592 auto [Mx, My, Mz] = c.max;
593 auto [ix, iy, iz] = c.init;
594 return new Process::XYZSpinboxes{{mx, my, mz}, {Mx, My, Mz}, {ix, iy, iz},
595 false, qname, id, parent};
596 }
597 }
598 else if constexpr(widg.widget == avnd::widget_type::xyzw_spinbox)
599 {
600 static constexpr auto c = avnd::get_range<T>();
601 if constexpr(requires {
602 c.min == 0.f;
603 c.max == 0.f;
604 c.init == 0.f;
605 })
606 {
607 return new Process::XYZSpinboxes{
608 {c.min, c.min, c.min},
609 {c.max, c.max, c.max},
610 {c.init, c.init, c.init},
611 false,
612 qname,
613 id,
614 parent};
615 }
616 else
617 {
618 auto [mx, my, mz, mw] = c.min;
619 auto [Mx, My, Mz, Mw] = c.max;
620 auto [ix, iy, iz, iw] = c.init;
621 // FIXME we don't have a good 4-way widget
622 return new Process::XYZSpinboxes{{mx, my, mz}, {Mx, My, Mz}, {ix, iy, iz},
623 false, qname, id, parent};
624 }
625 }
626 else if constexpr(widg.widget == avnd::widget_type::color)
627 {
628 static constexpr auto c = avnd::get_range<T>();
629 static constexpr auto i = c.init;
630 return new Process::HSVSlider{{i.r, i.g, i.b, i.a}, qname, id, parent};
631 }
632 else if constexpr(widg.widget == avnd::widget_type::control)
633 {
634 return new Process::ControlInlet{qname, id, parent};
635 }
636 else if constexpr(widg.widget == avnd::widget_type::no_control)
637 {
638 return new Process::ValueInlet{qname, id, parent};
639 }
640 else
641 {
642 static_assert(T::is_not_a_valid_control);
643 }
644}
645
646template <typename T, std::size_t N>
647static inline auto
648make_control_out(avnd::field_index<N>, Id<Process::Port>&& id, QObject* parent)
649{
650 constexpr auto name = avnd::get_name<T>();
651 constexpr auto widg = avnd::get_widget<T>();
652 QString qname = QString::fromUtf8(name.data(), name.size());
653
654 // FIXME log normalization & friends
655
656 if constexpr(widg.widget == avnd::widget_type::bargraph)
657 {
658 static constexpr auto c = avnd::get_range<T>();
659 return new Process::Bargraph{c.min, c.max, c.init, qname, id, parent};
660 }
661 else if constexpr(widg.widget == avnd::widget_type::control)
662 {
663 return new Process::ControlOutlet{qname, id, parent};
664 }
665 else if constexpr(widg.widget == avnd::widget_type::no_control)
666 {
667 return new Process::ValueOutlet{qname, id, parent};
668 }
669 else if constexpr(avnd::fp_ish<decltype(T::value)>)
670 {
671 static constexpr auto c = avnd::get_range<T>();
672 return new Process::Bargraph{c.min, c.max, c.init, qname, id, parent};
673 }
674 else
675 {
676 return new Process::ControlOutlet{qname, id, parent};
677 }
678}
679
680template <typename T>
681static inline constexpr auto make_control_out(const T& t)
682{
683 return make_control_out<T>();
684}
685}
Definition VisitorInterface.hpp:53
Definition DataStreamVisitor.hpp:27
Definition DataStreamVisitor.hpp:202
Definition VisitorInterface.hpp:61
Definition JSONVisitor.hpp:52
Definition JSONVisitor.hpp:423
Definition Port.hpp:242
Definition Port.hpp:476
Definition Port.hpp:542
Definition Port.hpp:568
Definition UuidKey.hpp:345
The id_base_t class.
Definition Identifier.hpp:59
Definition Concepts.hpp:49
Definition Controls.hpp:27
Definition CurveInlet.hpp:47
Definition WidgetInlets.hpp:781
Definition WidgetInlets.hpp:603
Definition WidgetInlets.hpp:373
Definition WidgetInlets.hpp:517
Definition WidgetInlets.hpp:568
Definition WidgetInlets.hpp:423
Definition WidgetInlets.hpp:178
Definition WidgetInlets.hpp:247
Definition WidgetInlets.hpp:283
Definition WidgetInlets.hpp:162
Definition WidgetInlets.hpp:318
Definition WidgetInlets.hpp:444
Definition WidgetInlets.hpp:629
Definition WidgetInlets.hpp:616
Definition WidgetInlets.hpp:229
Definition WidgetInlets.hpp:265
Definition WidgetInlets.hpp:212
Definition WidgetInlets.hpp:195
Definition WidgetInlets.hpp:730
Definition WidgetInlets.hpp:747
Definition WidgetInlets.hpp:763
Definition WidgetInlets.hpp:494
Definition WidgetInlets.hpp:334
Definition WidgetInlets.hpp:360
Definition WidgetInlets.hpp:646
Definition WidgetInlets.hpp:684
Definition WidgetInlets.hpp:665
Definition WidgetInlets.hpp:710
Definition Domain.hpp:17
Definition VisitorInterface.hpp:13
The VisitorVariant struct.
Definition VisitorInterface.hpp:26
Definition Concepts.hpp:74
Definition Concepts.hpp:101
Definition Concepts.hpp:120