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>
15 #include <avnd/concepts/layout.hpp>
20 template <
typename Info>
23 using inputs_type =
typename avnd::input_introspection<Info>::type;
24 using outputs_type =
typename avnd::output_introspection<Info>::type;
25 inputs_type temp_inputs;
26 outputs_type temp_outputs;
28 typename Info::ui* rootUi{};
30 template <
typename Item>
33 if constexpr(requires {
sizeof(Item::value); })
35 oscr::from_ossia_value(inl->value(), item.value);
36 if constexpr(requires { rootUi->on_control_update(); })
39 inl, &Process::ControlInlet::valueChanged, &context,
40 [rui = rootUi, layout = this->layout, &item](
const ossia::value& v) {
41 oscr::from_ossia_value(v, item.value);
43 rui->on_control_update();
50 inl, &Process::ControlInlet::valueChanged, &context,
51 [layout = this->layout, &item](
const ossia::value& v) {
52 oscr::from_ossia_value(v, item.value);
58 template <
typename Item>
59 QGraphicsItem* createControl(Item& item,
auto... member)
61 if constexpr(requires { ((inputs_type{}).*....*member); })
63 int index = avnd::index_in_struct(temp_inputs, member...);
64 auto [port, qitem] = makeInlet(index);
65 setupControl(port, item);
68 else if constexpr(requires { ((outputs_type{}).*....*member); })
70 int index = avnd::index_in_struct(temp_outputs, member...);
71 auto [port, qitem] = makeOutlet(index);
76 static_assert(
sizeof...(member) < 0,
"not_a_member_of_inputs_or_outputs");
82 template <
typename Item,
typename T>
83 QGraphicsItem* createWidget(Item& it,
const T& member)
85 if constexpr(requires {
88 } -> std::convertible_to<std::string_view>;
91 return makeLabel(member);
93 else if constexpr(requires {
96 } -> std::convertible_to<std::string_view>;
99 return makeLabel(member.text);
103 return createControl(it, member);
107 template <
typename Item,
typename... T>
108 requires(
sizeof...(T) > 1)
109 QGraphicsItem* createWidget(Item& item, T... recursive_members)
111 return createControl(item, recursive_members...);
114 template <
typename Item>
115 QGraphicsItem* createCustom(Item& item)
117 static_assert(!requires { item.transaction; });
121 template <
typename Item>
122 QGraphicsItem* createCustomControl(Item& item,
auto... member)
124 if constexpr(requires { ((inputs_type{}).*....*member); })
126 int index = avnd::index_in_struct(temp_inputs, member...);
128 if(
auto* port = qobject_cast<Process::ControlInlet*>(inlets[index]))
131 setupControl(port, item);
136 else if constexpr(requires { ((outputs_type{}).*....*member); })
138 int index = avnd::index_in_struct(temp_outputs, member...);
140 if(
auto* port = qobject_cast<Process::ControlOutlet*>(outlets[index]))
143 setupControl(port, item);
150 static_assert(
sizeof...(member) < 0,
"not_a_member_of_inputs_or_outputs");
169 template <
typename Item>
173 setupLayout(item, *new_l);
174 setupItem(item, *new_l);
176 createdLayouts.push_back(new_l);
179 using namespace boost::pfr;
180 using namespace boost::pfr::detail;
181 constexpr
int N = boost::pfr::tuple_size_v<Item>;
182 auto t = boost::pfr::detail::tie_as_tuple(item, size_t_<N>{});
183 [&]<std::size_t... I>(std::index_sequence<I...>)
185 (this->walkLayout(sequence_tuple::get<I>(t), recursive_members...), ...);
187 (make_index_sequence<N>{});
193 template <
typename Item>
194 void walkLayout(Item& item,
auto... recursive_members)
196 if constexpr(avnd::spacing_layout<Item>)
199 double w = 1., h = 1.;
200 if constexpr(requires { Item::width(); })
202 if constexpr(requires { Item::height(); })
204 widg->setRect({0, 0, w, h});
206 else if constexpr(avnd::container_layout<Item>)
210 else if constexpr(avnd::hbox_layout<Item> || avnd::group_layout<Item>)
214 else if constexpr(avnd::vbox_layout<Item>)
218 else if constexpr(avnd::split_layout<Item>)
222 else if constexpr(avnd::grid_layout<Item>)
224 if constexpr(requires { Item::columns(); })
227 new_l->setColumns(Item::columns());
228 subLayout(item, new_l, recursive_members...);
230 else if constexpr(requires { Item::rows(); })
233 new_l->setRows(Item::rows());
234 subLayout(item, new_l, recursive_members...);
237 else if constexpr(avnd::tab_layout<Item>)
240 avnd::for_each_field_ref(
241 item, [&]<
typename F>(F field) { new_l->addTab(F::name()); });
243 subLayout(item, new_l, recursive_members...);
245 else if constexpr(avnd::control_layout<Item>)
248 if(
auto widg = createWidget(item, recursive_members..., item.model))
249 setupItem(item, *widg);
251 else if constexpr(avnd::custom_control_layout<Item>)
254 if(
auto widg = createCustomControl(item, recursive_members..., item.model))
255 setupItem(item, *widg);
257 else if constexpr(avnd::custom_layout<Item>)
260 if(
auto widg = createCustom(item))
261 setupItem(item, *widg);
263 else if constexpr(avnd::recursive_group_layout<Item>)
265 walkLayout(item.ui, recursive_members..., item.group);
267 else if constexpr(avnd::has_layout<Item>)
275 if(
auto widg = createWidget(item, item))
276 setupItem(item, *widg);
281 template <
typename Info>
288 std::optional<double> recommendedHeight()
const noexcept
override
290 if constexpr(requires { (double)Info::layout::height(); })
292 return Info::layout::height();
294 return Process::LayerFactory::recommendedHeight();
309 QGraphicsItem* parent)
const final override
324 if constexpr(requires {
sizeof(
typename Info::ui::bus); })
328 using score::EmptyRectItem::EmptyRectItem;
329 typename Info::ui ui;
330 typename Info::ui::bus bus;
332 auto ptr =
new Item{parent};
334 if constexpr(avnd::has_gui_to_processor_bus<Info>)
340 if constexpr(avnd::has_processor_to_gui_bus<Info>)
343 proc.to_ui = [ptr = QPointer{ptr}](QByteArray mess) {
348 if constexpr(requires { ptr->bus.process_message(); })
350 ptr->bus.process_message();
352 else if constexpr(requires { ptr->bus.process_message(ptr->ui); })
354 ptr->bus.process_message(ptr->ui);
356 else if constexpr(requires { ptr->bus.process_message(ptr->ui, {}); })
358 std::decay_t<avnd::second_argument<&Info::ui::bus::process_message>> arg;
361 ptr->bus.process_message(ptr->ui, std::move(arg));
365 ptr->bus.process_message(ptr->ui, {});
370 if_possible(ptr->bus.init(ptr->ui));
377 using score::EmptyRectItem::EmptyRectItem;
378 typename Info::ui ui;
380 return new Item{parent};
386 QGraphicsItem* parent)
const final override
388 using namespace score;
390 auto rootItem = makeItemImpl(
397 b.rootUi = &rootItem->ui;
399 b.walkLayout(rootItem->ui);
401 b.finalizeLayout(rootItem);
403 rootItem->fitChildrenRect();
405 if_possible(b.rootUi->on_control_update());
Definition: score-lib-process/Process/Dataflow/Port.hpp:202
Definition: score-lib-process/Process/ProcessFactory.hpp:58
Definition: LayerPresenter.hpp:34
Definition: LayerView.hpp:21
Definition: PortFactory.hpp:65
The Process class.
Definition: score-lib-process/Process/Process.hpp:61
Definition: Painter.hpp:345
Definition: Painter.hpp:189
Definition: score-plugin-avnd/Crousti/Layer.hpp:283
Definition: score-plugin-avnd/Crousti/ProcessModel.hpp:551
Definition: RectItem.hpp:64
Definition: GraphicsGridLayout.hpp:9
Definition: GraphicsGridLayout.hpp:23
Definition: GraphicsBoxLayout.hpp:9
Definition: GraphicsLayout.hpp:10
Definition: GraphicsSplitLayout.hpp:9
Definition: GraphicsTabLayout.hpp:11
Definition: GraphicsBoxLayout.hpp:18
Definition: RectItem.hpp:12
Base toolkit upon which the software is built.
Definition: Application.cpp:90
Definition: ProcessContext.hpp:12
Definition: plugins/score-lib-process/Control/Layout.hpp:11
Definition: ObjectMatches.hpp:6
Definition: score-plugin-avnd/Crousti/Layer.hpp:22
Definition: MessageBus.hpp:120
Definition: MessageBus.hpp:37
const T & interfaces() const
Access to a specific interface list.
Definition: ApplicationContext.hpp:67