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);
173 if constexpr(
requires { item.set = {}; })
175 item.set = [inl](
const auto& val) { inl->setValue(oscr::to_ossia_value(val)); };
179 if constexpr(
requires { Item::dynamic_size; })
183 if(
auto edit = qgraphicsitem_cast<score::QGraphicsLineEdit*>(lay.control))
185 edit, &score::QGraphicsLineEdit::sizeChanged, obj,
186 &score::ResizeableItem::childrenSizeChanged);
189 if constexpr(
requires { Item::width; })
191 if(
auto edit = qgraphicsitem_cast<score::QGraphicsLineEdit*>(lay.control))
192 edit->setTextWidth(Item::width());
196 template <
typename Item>
197 void createControl(Item& item,
auto... member)
199 if constexpr(
requires { ((inputs_type{}).*....*member); })
201 int index = avnd::index_in_struct(temp_inputs, member...);
203 auto ports = proc.avnd_input_idx_to_model_ports(index);
206 auto [port, qitem] = makeInlet(p);
209 SCORE_ASSERT(qitem.container);
210 setupControl(this->layout, port, qitem, item);
211 setupItem(item, *qitem.container);
215 else if constexpr(
requires { ((outputs_type{}).*....*member); })
217 int index = avnd::index_in_struct(temp_outputs, member...);
219 auto ports = proc.avnd_output_idx_to_model_ports(index);
222 auto [port, qitem] = makeOutlet(p);
225 SCORE_ASSERT(qitem.container);
226 setupControl(this->layout, port, qitem, item);
227 setupItem(item, *qitem.container);
233 static_assert(
sizeof...(member) < 0,
"not_a_member_of_inputs_or_outputs");
237 template <
typename Item,
typename T>
238 void createWidget(Item& it,
const T& member)
240 if constexpr(
requires {
241 { member } -> std::convertible_to<std::string_view>;
244 auto res = makeLabel(member);
247 else if constexpr(
requires {
248 { member.text } -> std::convertible_to<std::string_view>;
251 auto res = makeLabel(member.text);
256 createControl(it, member);
260 template <
typename Item,
typename... T>
261 requires(
sizeof...(T) > 1)
262 void createWidget(Item& item, T... recursive_members)
264 createControl(item, recursive_members...);
267 template <
typename Item>
268 void createCustom(Item& item)
270 static_assert(!
requires { item.transaction; });
272 setupItem(item, *res);
275 template <
typename Item>
276 void createCustomControl(Item& item,
auto... member)
278 if constexpr(
requires { ((inputs_type{}).*....*member); })
280 int index = avnd::index_in_struct(temp_inputs, member...);
283 auto ports = proc.avnd_input_idx_to_model_ports(index);
286 if(
auto* port = qobject_cast<Process::ControlInlet*>(p))
290 if(
auto* f = portFactory.
get(port->concreteKey()))
292 lay.port_item = f->makePortItem(*port, this->doc, this->layout, &context);
294 setupControl(this->layout, port, lay, item);
295 setupItem(item, *qitem);
299 else if constexpr(
requires { ((outputs_type{}).*....*member); })
301 int index = avnd::index_in_struct(temp_outputs, member...);
304 auto ports = proc.avnd_output_idx_to_model_ports(index);
307 if(
auto* port = qobject_cast<Process::ControlOutlet*>(p))
311 if(
auto* f = portFactory.
get(port->concreteKey()))
313 lay.port_item = f->makePortItem(*port, this->doc, this->layout, &context);
315 setupControl(this->layout, port, lay, item);
316 setupItem(item, *qitem);
322 static_assert(
sizeof...(member) < 0,
"not_a_member_of_inputs_or_outputs");
326 template <
typename Item>
330 setupLayout(item, *new_l);
331 setupItem(item, *new_l);
333 createdLayouts.push_back(new_l);
336 using namespace boost::pfr;
337 using namespace boost::pfr::detail;
338 static constexpr int N = boost::pfr::tuple_size_v<Item>;
339 auto t = boost::pfr::detail::tie_as_tuple(item, size_t_<N>{});
340 [&]<std::size_t... I>(std::index_sequence<I...>) {
341 (this->walkLayout(sequence_tuple::get<I>(t), recursive_members...), ...);
342 }(std::make_index_sequence<N>{});
348 template <
typename Item>
349 auto initRecursiveLayout()
351 auto new_l = createRecursiveLayout<Item>(this->layout);
352 setupRecursiveLayout<Item>(new_l);
356 template <
typename Item>
357 void walkLayout(Item& item,
auto... recursive_members)
359 if constexpr(avnd::spacing_layout<Item>)
362 double w = 1., h = 1.;
363 if constexpr(
requires { Item::width(); })
365 if constexpr(
requires { Item::height(); })
367 widg->setRect({0, 0, w, h});
371 subLayout(item, initRecursiveLayout<Item>(), recursive_members...);
373 else if constexpr(avnd::control_layout<Item>)
377 createWidget(item, recursive_members..., item.model);
379 else if constexpr(avnd::custom_control_layout<Item>)
383 createCustomControl(item, recursive_members..., item.model);
385 else if constexpr(avnd::custom_layout<Item>)
391 else if constexpr(avnd::recursive_group_layout<Item>)
393 walkLayout(item.ui, recursive_members..., item.group);
395 else if constexpr(avnd::dynamic_controls<Item>)
397 walkLayout(item.ui, recursive_members..., item.group);
399 else if constexpr(avnd::has_layout<Item>)
402 subLayout(item, initRecursiveLayout<Item>(), recursive_members...);
407 createWidget(item, item);
419 std::optional<double> recommendedHeight()
const noexcept override
421 if constexpr(
requires { (double)Info::layout::height(); })
423 return Info::layout::height();
425 return Process::LayerFactory::recommendedHeight();
440 QGraphicsItem* parent)
const final override
452 template <
typename Item>
456 if constexpr(avnd::has_gui_to_processor_bus<Info>)
462 if constexpr(avnd::has_processor_to_gui_bus<Info>)
465 proc.to_ui = [ptr = QPointer{ptr}](QByteArray mess) {
470 if constexpr(
requires { ptr->bus.process_message(); })
472 ptr->bus.process_message();
474 else if constexpr(
requires { ptr->bus.process_message(ptr->ui); })
476 ptr->bus.process_message(ptr->ui);
478 else if constexpr(
requires { ptr->bus.process_message(ptr->ui, {}); })
480 std::decay_t<avnd::second_argument<&Info::ui::bus::process_message>> arg;
483 ptr->bus.process_message(ptr->ui, std::move(arg));
487 ptr->bus.process_message(ptr->ui, {});
492 if_possible(ptr->bus.init(ptr->ui));
497 using ui_type =
typename Info::ui;
498 using root_layout_type
499 = std::remove_cvref_t<decltype(*createRecursiveLayout<ui_type>(
nullptr))>;
502 setupRecursiveLayout<ui_type>(new_l);
503 if constexpr(
requires {
sizeof(
typename Info::ui::bus); })
504 init_bus(proc, *new_l);
506 if constexpr(
requires { new_l->ui.start(); })
508 QObject::connect(&proc, &Process::ProcessModel::startExecution, new_l, [new_l] {
512 if constexpr(
requires { new_l->ui.stop(); })
514 QObject::connect(&proc, &Process::ProcessModel::stopExecution, new_l, [new_l] {
518 if constexpr(
requires { new_l->ui.reset(); })
520 QObject::connect(&proc, &Process::ProcessModel::resetExecution, new_l, [new_l] {
529 QGraphicsItem* parent)
const final override
531 using namespace score;
532 auto& process =
static_cast<const ProcessModel<Info>&
>(proc);
534 auto rootItem = makeItemImpl(
const_cast<ProcessModel<Info>&
>(process), parent);
536 auto recreate = [parent, &proc, &ctx, rootItem] {
537 LayoutBuilder<Info> b{
540 proc.inlets(), proc.outlets(),
542 b.rootUi = &rootItem->ui;
545 b.subLayout(rootItem->ui, rootItem);
547 b.finalizeLayout(rootItem);
549 rootItem->fitChildrenRect();
551 if_possible(b.rootUi->on_control_update());
554 QObject::connect(&proc, &Process::ProcessModel::inletsChanged, rootItem, [=]() {
555 auto cld = rootItem->childItems();
562 QObject::connect(&proc, &Process::ProcessModel::outletsChanged, rootItem, [=]() {
563 auto cld = rootItem->childItems();