128 using inputs_type =
typename avnd::input_introspection<Info>::type;
129 using outputs_type =
typename avnd::output_introspection<Info>::type;
130 inputs_type temp_inputs{};
131 outputs_type temp_outputs{};
133 typename Info::ui* rootUi{};
135 template <
typename Item>
141 template <
typename Item>
146 if constexpr(
requires {
sizeof(Item::value); })
148 using avnd_port_type = pmf_member_type_t<
decltype(item.model)>;
150 oscr::from_ossia_value(p, inl->value(), item.value);
151 if constexpr(
requires { rootUi->on_control_update(); })
154 inl, &Process::ControlInlet::valueChanged, &context,
155 [rui = rootUi, layout = this->layout, &item](
const ossia::value& v) {
157 oscr::from_ossia_value(p, v, item.value);
159 rui->on_control_update();
166 inl, &Process::ControlInlet::valueChanged, &context,
167 [layout = this->layout, &item](
const ossia::value& v) {
169 oscr::from_ossia_value(p, v, item.value);
174 if constexpr(
requires { item.set = {}; })
176 item.set = [inl](
const auto& val) { inl->setValue(oscr::to_ossia_value(val)); };
180 if constexpr(
requires { Item::dynamic_size; })
184 if(
auto edit = qgraphicsitem_cast<score::QGraphicsLineEdit*>(lay.control))
186 edit, &score::QGraphicsLineEdit::sizeChanged, obj,
187 &score::ResizeableItem::childrenSizeChanged);
190 if constexpr(
requires { Item::width; })
192 if(
auto edit = qgraphicsitem_cast<score::QGraphicsLineEdit*>(lay.control))
193 edit->setTextWidth(Item::width());
197 template <
typename Item>
198 void createControl(Item& item,
auto... member)
200 if constexpr(
requires { ((inputs_type{}).*....*member); })
202 int index = avnd::index_in_struct(temp_inputs, member...);
204 auto ports = proc.avnd_input_idx_to_model_ports(index);
207 auto [port, qitem] = makeInlet(p);
210 SCORE_ASSERT(qitem.container);
211 setupControl(this->layout, port, qitem, item);
212 setupItem(item, *qitem.container);
216 else if constexpr(
requires { ((outputs_type{}).*....*member); })
218 int index = avnd::index_in_struct(temp_outputs, member...);
220 auto ports = proc.avnd_output_idx_to_model_ports(index);
223 auto [port, qitem] = makeOutlet(p);
226 SCORE_ASSERT(qitem.container);
227 setupControl(this->layout, port, qitem, item);
228 setupItem(item, *qitem.container);
234 static_assert(
sizeof...(member) < 0,
"not_a_member_of_inputs_or_outputs");
238 template <
typename Item,
typename T>
239 void createWidget(Item& it,
const T& member)
241 if constexpr(
requires {
242 { member } -> std::convertible_to<std::string_view>;
245 auto res = makeLabel(member);
248 else if constexpr(
requires {
249 { member.text } -> std::convertible_to<std::string_view>;
252 auto res = makeLabel(member.text);
257 createControl(it, member);
261 template <
typename Item,
typename... T>
262 requires(
sizeof...(T) > 1)
263 void createWidget(Item& item, T... recursive_members)
265 createControl(item, recursive_members...);
268 template <
typename Item>
269 void createCustom(Item& item)
271 static_assert(!
requires { item.transaction; });
273 setupItem(item, *res);
276 template <
typename Item>
277 void createCustomControl(Item& item,
auto... member)
279 if constexpr(
requires { ((inputs_type{}).*....*member); })
281 int index = avnd::index_in_struct(temp_inputs, member...);
284 auto ports = proc.avnd_input_idx_to_model_ports(index);
287 if(
auto* port = qobject_cast<Process::ControlInlet*>(p))
291 if(
auto* f = portFactory.
get(port->concreteKey()))
293 lay.port_item = f->makePortItem(*port, this->doc, this->layout, &context);
295 setupControl(this->layout, port, lay, item);
296 setupItem(item, *qitem);
300 else if constexpr(
requires { ((outputs_type{}).*....*member); })
302 int index = avnd::index_in_struct(temp_outputs, member...);
305 auto ports = proc.avnd_output_idx_to_model_ports(index);
308 if(
auto* port = qobject_cast<Process::ControlOutlet*>(p))
312 if(
auto* f = portFactory.
get(port->concreteKey()))
314 lay.port_item = f->makePortItem(*port, this->doc, this->layout, &context);
316 setupControl(this->layout, port, lay, item);
317 setupItem(item, *qitem);
323 static_assert(
sizeof...(member) < 0,
"not_a_member_of_inputs_or_outputs");
327 template <
typename Item>
331 setupLayout(item, *new_l);
332 setupItem(item, *new_l);
334 createdLayouts.push_back(new_l);
337#if AVND_USE_BOOST_PFR
338 static constexpr int N = avnd::pfr::tuple_size_v<Item>;
339 auto t = avnd::pfr::detail::tie_as_tuple(item);
340 [&]<std::size_t... I>(std::index_sequence<I...>) {
342 using namespace avnd::pfr;
344 (this->walkLayout(get<I>(t), recursive_members...), ...);
345 }(std::make_index_sequence<N>{});
347 auto&& [... members] = item;
348 (this->walkLayout(members, recursive_members...), ...);
355 template <
typename Item>
356 auto initRecursiveLayout()
358 auto new_l = createRecursiveLayout<Item>(this->layout);
359 setupRecursiveLayout<Item>(new_l);
363 template <
typename Item>
364 void walkLayout(Item& item,
auto... recursive_members)
366 if constexpr(avnd::spacing_layout<Item>)
369 double w = 1., h = 1.;
370 if constexpr(
requires { Item::width(); })
372 if constexpr(
requires { Item::height(); })
374 widg->setRect({0, 0, w, h});
378 subLayout(item, initRecursiveLayout<Item>(), recursive_members...);
380 else if constexpr(avnd::control_layout<Item>)
384 createWidget(item, recursive_members..., item.model);
386 else if constexpr(avnd::custom_control_layout<Item>)
390 createCustomControl(item, recursive_members..., item.model);
392 else if constexpr(avnd::custom_layout<Item>)
398 else if constexpr(avnd::recursive_group_layout<Item>)
400 walkLayout(item.ui, recursive_members..., item.group);
402 else if constexpr(avnd::dynamic_controls<Item>)
404 walkLayout(item.ui, recursive_members..., item.group);
406 else if constexpr(avnd::has_layout<Item>)
409 subLayout(item, initRecursiveLayout<Item>(), recursive_members...);
414 createWidget(item, item);
426 std::optional<double> recommendedHeight()
const noexcept override
428 if constexpr(
requires { (double)Info::layout::height(); })
430 return Info::layout::height();
432 return Process::LayerFactory::recommendedHeight();
447 QGraphicsItem* parent)
const final override
459 template <
typename Item>
463 if constexpr(avnd::has_gui_to_processor_bus<Info>)
469 if constexpr(avnd::has_processor_to_gui_bus<Info>)
472 proc.to_ui = [ptr = QPointer{ptr}](QByteArray mess) {
477 if constexpr(
requires { ptr->bus.process_message(); })
479 ptr->bus.process_message();
481 else if constexpr(
requires { ptr->bus.process_message(ptr->ui); })
483 ptr->bus.process_message(ptr->ui);
485 else if constexpr(
requires { ptr->bus.process_message(ptr->ui, {}); })
487 std::decay_t<avnd::second_argument<&Info::ui::bus::process_message>> arg;
490 ptr->bus.process_message(ptr->ui, std::move(arg));
494 ptr->bus.process_message(ptr->ui, {});
499 if_possible(ptr->bus.init(ptr->ui));
504 using ui_type =
typename Info::ui;
505 using root_layout_type
506 = std::remove_cvref_t<decltype(*createRecursiveLayout<ui_type>(
nullptr))>;
509 setupRecursiveLayout<ui_type>(new_l);
510 if constexpr(
requires {
sizeof(
typename Info::ui::bus); })
511 init_bus(proc, *new_l);
513 if constexpr(
requires { new_l->ui.start(); })
515 QObject::connect(&proc, &Process::ProcessModel::startExecution, new_l, [new_l] {
519 if constexpr(
requires { new_l->ui.stop(); })
521 QObject::connect(&proc, &Process::ProcessModel::stopExecution, new_l, [new_l] {
525 if constexpr(
requires { new_l->ui.reset(); })
527 QObject::connect(&proc, &Process::ProcessModel::resetExecution, new_l, [new_l] {
536 QGraphicsItem* parent)
const final override
538 using namespace score;
539 auto& process =
static_cast<const ProcessModel<Info>&
>(proc);
541 auto rootItem = makeItemImpl(
const_cast<ProcessModel<Info>&
>(process), parent);
543 auto recreate = [parent, &proc, &ctx, rootItem] {
544 LayoutBuilder<Info> b{
547 proc.inlets(), proc.outlets(),
549 b.rootUi = &rootItem->ui;
552 b.subLayout(rootItem->ui, rootItem);
554 b.finalizeLayout(rootItem);
556 rootItem->fitChildrenRect();
558 if_possible(b.rootUi->on_control_update());
561 QObject::connect(&proc, &Process::ProcessModel::inletsChanged, rootItem, [=]() {
562 auto cld = rootItem->childItems();
569 QObject::connect(&proc, &Process::ProcessModel::outletsChanged, rootItem, [=]() {
570 auto cld = rootItem->childItems();