2 #include <Process/LayerPresenter.hpp>
3 #include <Process/LayerView.hpp>
5 #include <Control/Layout.hpp>
6 #include <Crousti/MessageBus.hpp>
7 #include <Crousti/Painter.hpp>
8 #include <Crousti/ProcessModel.hpp>
10 #include <score/graphics/layouts/GraphicsBoxLayout.hpp>
11 #include <score/graphics/layouts/GraphicsGridLayout.hpp>
12 #include <score/graphics/layouts/GraphicsSplitLayout.hpp>
13 #include <score/graphics/layouts/GraphicsTabLayout.hpp>
14 #include <score/graphics/widgets/QGraphicsLineEdit.hpp>
16 #include <avnd/concepts/layout.hpp>
20 template <
typename Item>
21 concept recursive_container_layout
22 = avnd::container_layout<Item> || avnd::hbox_layout<Item> || avnd::group_layout<Item>
23 || avnd::vbox_layout<Item> || avnd::split_layout<Item> || avnd::grid_layout<Item>
24 || avnd::tab_layout<Item>;
26 template <
typename Info>
30 template <
typename Info>
31 requires requires {
sizeof(
typename Info::ui::bus); }
34 typename Info::ui::bus bus;
37 template <
typename Info,
typename RootLayout>
42 using RootLayout::RootLayout;
46 template <
typename Item>
47 static auto createRecursiveLayout(QGraphicsItem* parent)
49 if constexpr(avnd::container_layout<Item>)
53 else if constexpr(avnd::hbox_layout<Item> || avnd::group_layout<Item>)
57 else if constexpr(avnd::vbox_layout<Item>)
61 else if constexpr(avnd::split_layout<Item>)
65 else if constexpr(avnd::grid_layout<Item>)
67 if constexpr(requires { Item::columns(); })
71 else if constexpr(requires { Item::rows(); })
76 else if constexpr(avnd::tab_layout<Item>)
80 else if constexpr(avnd::has_layout<Item>)
91 template <
typename Item>
92 static void setupRecursiveLayout(
auto* new_l)
94 if constexpr(avnd::grid_layout<Item>)
96 if constexpr(requires { Item::columns(); })
98 new_l->setColumns(Item::columns());
100 else if constexpr(requires { Item::rows(); })
102 new_l->setRows(Item::rows());
105 else if constexpr(avnd::tab_layout<Item>)
107 [=]<
typename... Ts>(avnd::typelist<Ts...> args) {
108 (new_l->addTab(Ts::name()), ...);
109 }(avnd::as_typelist<Item>{});
113 template <
typename T>
115 template <
typename T,
typename V>
121 template <
typename T>
124 template <
typename Info>
127 using inputs_type =
typename avnd::input_introspection<Info>::type;
128 using outputs_type =
typename avnd::output_introspection<Info>::type;
129 inputs_type temp_inputs{};
130 outputs_type temp_outputs{};
132 typename Info::ui* rootUi{};
134 template <
typename Item>
140 template <
typename Item>
145 if constexpr(requires {
sizeof(Item::value); })
147 using avnd_port_type = pmf_member_type_t<decltype(item.model)>;
149 oscr::from_ossia_value(p, inl->value(), item.value);
150 if constexpr(requires { rootUi->on_control_update(); })
153 inl, &Process::ControlInlet::valueChanged, &context,
154 [rui = rootUi, layout = this->layout, &item](
const ossia::value& v) {
156 oscr::from_ossia_value(p, v, item.value);
158 rui->on_control_update();
165 inl, &Process::ControlInlet::valueChanged, &context,
166 [layout = this->layout, &item](
const ossia::value& v) {
168 oscr::from_ossia_value(p, v, item.value);
174 if constexpr(requires { Item::dynamic_size; })
178 if(
auto edit = qgraphicsitem_cast<score::QGraphicsLineEdit*>(lay.control))
180 edit, &score::QGraphicsLineEdit::sizeChanged, obj,
181 &score::ResizeableItem::childrenSizeChanged);
186 template <
typename Item>
187 void createControl(Item& item,
auto... member)
189 if constexpr(requires { ((inputs_type{}).*....*member); })
191 int index = avnd::index_in_struct(temp_inputs, member...);
193 auto ports = proc.avnd_input_idx_to_model_ports(index);
196 auto [port, qitem] = makeInlet(p);
199 SCORE_ASSERT(qitem.container);
200 setupControl(this->layout, port, qitem, item);
201 setupItem(item, *qitem.container);
205 else if constexpr(requires { ((outputs_type{}).*....*member); })
207 int index = avnd::index_in_struct(temp_outputs, member...);
209 auto ports = proc.avnd_output_idx_to_model_ports(index);
212 auto [port, qitem] = makeOutlet(p);
215 SCORE_ASSERT(qitem.container);
216 setupControl(this->layout, port, qitem, item);
217 setupItem(item, *qitem.container);
223 static_assert(
sizeof...(member) < 0,
"not_a_member_of_inputs_or_outputs");
227 template <
typename Item,
typename T>
228 void createWidget(Item& it,
const T& member)
230 if constexpr(requires {
231 { member } -> std::convertible_to<std::string_view>;
234 auto res = makeLabel(member);
237 else if constexpr(requires {
238 { member.text } -> std::convertible_to<std::string_view>;
241 auto res = makeLabel(member.text);
246 createControl(it, member);
250 template <
typename Item,
typename... T>
251 requires(
sizeof...(T) > 1)
252 void createWidget(Item& item, T... recursive_members)
254 createControl(item, recursive_members...);
257 template <
typename Item>
258 void createCustom(Item& item)
260 static_assert(!requires { item.transaction; });
262 setupItem(item, *res);
265 template <
typename Item>
266 void createCustomControl(Item& item,
auto... member)
268 if constexpr(requires { ((inputs_type{}).*....*member); })
270 int index = avnd::index_in_struct(temp_inputs, member...);
273 auto ports = proc.avnd_input_idx_to_model_ports(index);
276 if(
auto* port = qobject_cast<Process::ControlInlet*>(p))
280 setupControl(this->layout, port, lay, item);
281 setupItem(item, *qitem);
285 else if constexpr(requires { ((outputs_type{}).*....*member); })
287 int index = avnd::index_in_struct(temp_outputs, member...);
290 auto ports = proc.avnd_output_idx_to_model_ports(index);
293 if(
auto* port = qobject_cast<Process::ControlOutlet*>(p))
297 setupControl(this->layout, port, lay, item);
298 setupItem(item, *qitem);
304 static_assert(
sizeof...(member) < 0,
"not_a_member_of_inputs_or_outputs");
308 template <
typename Item>
312 setupLayout(item, *new_l);
313 setupItem(item, *new_l);
315 createdLayouts.push_back(new_l);
318 using namespace boost::pfr;
319 using namespace boost::pfr::detail;
320 static constexpr
int N = boost::pfr::tuple_size_v<Item>;
321 auto t = boost::pfr::detail::tie_as_tuple(item, size_t_<N>{});
322 [&]<std::size_t... I>(std::index_sequence<I...>) {
323 (this->walkLayout(sequence_tuple::get<I>(t), recursive_members...), ...);
324 }(std::make_index_sequence<N>{});
330 template <
typename Item>
331 auto initRecursiveLayout()
333 auto new_l = createRecursiveLayout<Item>(this->layout);
334 setupRecursiveLayout<Item>(new_l);
338 template <
typename Item>
339 void walkLayout(Item& item,
auto... recursive_members)
341 if constexpr(avnd::spacing_layout<Item>)
344 double w = 1., h = 1.;
345 if constexpr(requires { Item::width(); })
347 if constexpr(requires { Item::height(); })
349 widg->setRect({0, 0, w, h});
351 else if constexpr(recursive_container_layout<Item>)
353 subLayout(item, initRecursiveLayout<Item>(), recursive_members...);
355 else if constexpr(avnd::control_layout<Item>)
359 createWidget(item, recursive_members..., item.model);
361 else if constexpr(avnd::custom_control_layout<Item>)
365 createCustomControl(item, recursive_members..., item.model);
367 else if constexpr(avnd::custom_layout<Item>)
373 else if constexpr(avnd::recursive_group_layout<Item>)
375 walkLayout(item.ui, recursive_members..., item.group);
377 else if constexpr(avnd::dynamic_controls<Item>)
379 walkLayout(item.ui, recursive_members..., item.group);
381 else if constexpr(avnd::has_layout<Item>)
384 subLayout(item, initRecursiveLayout<Item>(), recursive_members...);
389 createWidget(item, item);
394 template <
typename Info>
401 std::optional<double> recommendedHeight()
const noexcept
override
403 if constexpr(requires { (double)Info::layout::height(); })
405 return Info::layout::height();
407 return Process::LayerFactory::recommendedHeight();
422 QGraphicsItem* parent)
const final override
434 template <
typename Item>
438 if constexpr(avnd::has_gui_to_processor_bus<Info>)
444 if constexpr(avnd::has_processor_to_gui_bus<Info>)
447 proc.to_ui = [ptr = QPointer{ptr}](QByteArray mess) {
452 if constexpr(requires { ptr->bus.process_message(); })
454 ptr->bus.process_message();
456 else if constexpr(requires { ptr->bus.process_message(ptr->ui); })
458 ptr->bus.process_message(ptr->ui);
460 else if constexpr(requires { ptr->bus.process_message(ptr->ui, {}); })
462 std::decay_t<avnd::second_argument<&Info::ui::bus::process_message>> arg;
465 ptr->bus.process_message(ptr->ui, std::move(arg));
469 ptr->bus.process_message(ptr->ui, {});
474 if_possible(ptr->bus.init(ptr->ui));
479 using ui_type =
typename Info::ui;
480 using root_layout_type
481 = std::remove_cvref_t<decltype(*createRecursiveLayout<ui_type>(
nullptr))>;
484 setupRecursiveLayout<ui_type>(new_l);
485 if constexpr(requires {
sizeof(
typename Info::ui::bus); })
486 init_bus(proc, *new_l);
492 QGraphicsItem* parent)
const final override
494 using namespace score;
499 auto recreate = [parent, &proc, &ctx, rootItem] {
503 proc.inlets(), proc.outlets(),
505 b.rootUi = &rootItem->ui;
508 b.subLayout(rootItem->ui, rootItem);
510 b.finalizeLayout(rootItem);
512 rootItem->fitChildrenRect();
514 if_possible(b.rootUi->on_control_update());
517 QObject::connect(&proc, &Process::ProcessModel::inletsChanged, rootItem, [=]() {
518 auto cld = rootItem->childItems();
525 QObject::connect(&proc, &Process::ProcessModel::outletsChanged, rootItem, [=]() {
526 auto cld = rootItem->childItems();
Definition: score-lib-process/Process/ProcessFactory.hpp:58
Definition: LayerPresenter.hpp:34
Definition: LayerView.hpp:21
Definition: PortFactory.hpp:74
The Process class.
Definition: score-lib-process/Process/Process.hpp:61
Definition: Painter.hpp:350
Definition: Painter.hpp:194
Definition: score-plugin-avnd/Crousti/Layer.hpp:396
Definition: score-plugin-avnd/Crousti/ProcessModel.hpp:77
Definition: RectItem.hpp:64
Definition: GraphicsGridLayout.hpp:9
Definition: GraphicsGridLayout.hpp:23
Definition: GraphicsBoxLayout.hpp:9
Definition: GraphicsLayout.hpp:8
Definition: GraphicsSplitLayout.hpp:9
Definition: GraphicsTabLayout.hpp:9
Definition: GraphicsBoxLayout.hpp:18
Definition: RectItem.hpp:12
Definition: Factories.hpp:19
Base toolkit upon which the software is built.
Definition: Application.cpp:90
Definition: ProcessContext.hpp:12
Definition: PortFactory.hpp:21
Definition: plugins/score-lib-process/Control/Layout.hpp:16
Definition: ObjectMatches.hpp:6
Definition: score-plugin-avnd/Crousti/Layer.hpp:126
Definition: MessageBus.hpp:133
Definition: MessageBus.hpp:37
Definition: score-plugin-avnd/Crousti/Layer.hpp:28
Definition: score-plugin-avnd/Crousti/Layer.hpp:41
Definition: score-plugin-avnd/Crousti/Layer.hpp:114