Loading...
Searching...
No Matches
plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp
1#pragma once
2#include <Process/Commands/SetControlValue.hpp>
3#include <Process/Dataflow/ControlWidgetDomains.hpp>
4#include <Process/Dataflow/Port.hpp>
5#include <Process/Dataflow/TimeSignature.hpp>
6#include <Process/Dataflow/WidgetInlets.hpp>
7#include <Process/Script/ScriptEditor.hpp>
8
9#include <score/command/Dispatchers/CommandDispatcher.hpp>
10#include <score/document/DocumentContext.hpp>
11#include <score/graphics/GraphicWidgets.hpp>
12#include <score/graphics/GraphicsItem.hpp>
13#include <score/graphics/RectItem.hpp>
14#include <score/graphics/TextItem.hpp>
15#include <score/tools/Unused.hpp>
16#include <score/widgets/ComboBox.hpp>
17#include <score/widgets/ControlWidgets.hpp>
18#include <score/widgets/HelpInteraction.hpp>
19#include <score/widgets/SignalUtils.hpp>
20
21#include <ossia/detail/algorithms.hpp>
22#include <ossia/network/domain/domain_functions.hpp>
23#include <ossia/network/value/value_conversion.hpp>
24
25#include <ossia-qt/invoke.hpp>
26
27#include <QAction>
28#include <QApplication>
29#include <QCheckBox>
30#include <QFileDialog>
31#include <QGraphicsItem>
32#include <QGraphicsSceneDragDropEvent>
33#include <QLineEdit>
34#include <QPalette>
35#include <QTextDocument>
36
37#include <score_lib_process_export.h>
38
39#include <verdigris>
40namespace Process
41{
42
43struct SCORE_LIB_PROCESS_EXPORT DefaultControlLayouts
44{
45 static Process::PortItemLayout knob() noexcept;
46 static Process::PortItemLayout slider() noexcept;
47 static Process::PortItemLayout combo() noexcept;
48 static Process::PortItemLayout list() noexcept;
49 static Process::PortItemLayout lineedit() noexcept;
50 static Process::PortItemLayout spinbox() noexcept;
51 static Process::PortItemLayout toggle() noexcept;
52 static Process::PortItemLayout pad() noexcept;
53 static Process::PortItemLayout bang() noexcept;
54 static Process::PortItemLayout button() noexcept;
55 static Process::PortItemLayout chooser_toggle() noexcept;
56};
57}
58
59namespace WidgetFactory
60{
61static_assert(std::numeric_limits<float>::is_iec559, "IEEE 754 required");
62template <typename T>
63using SetControlValue = typename std::conditional_t<
64 std::is_base_of<Process::ControlInlet, T>::value, Process::SetControlValue,
66
67template <typename Normalizer, typename T>
68using ConcreteNormalizer = std::conditional_t<
69 std::is_base_of_v<Process::ControlInlet, T>
70 || std::is_base_of_v<Process::ControlOutlet, T>,
71 UpdatingNormalizer<Normalizer, T>, FixedNormalizer<Normalizer>>;
72template <typename ControlUI, typename Normalizer, bool Control>
74{
75 static Process::PortItemLayout layout() noexcept
76 {
77 using namespace Process;
78 if constexpr(
79 std::is_same_v<score::QGraphicsKnob, ControlUI>
80 || std::is_same_v<score::QGraphicsLogKnob, ControlUI>)
81 {
82 return DefaultControlLayouts::knob();
83 }
84 else
85 {
86 return DefaultControlLayouts::slider();
87 }
88 }
89
90 template <typename T>
91 static auto make_widget(
92 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
93 {
94 ConcreteNormalizer<Normalizer, T> norm{inlet};
95
96 auto sl = new score::ValueDoubleSlider{parent};
97 sl->setOrientation(Qt::Horizontal);
98 sl->setContentsMargins(0, 0, 0, 0);
99 bindFloatDomain(inlet, inlet, *sl);
100 sl->setValue(norm.to01(ossia::convert<double>(inlet.value())));
101
102 if constexpr(Control)
103 {
104 QObject::connect(
105 sl, &score::DoubleSlider::sliderMoved, context,
106 [sl, norm, &inlet, &ctx](double v) {
107 sl->moving = true;
108 ctx.dispatcher.submit<SetControlValue<T>>(inlet, norm.from01(sl->value()));
109 });
110 QObject::connect(
111 sl, &score::DoubleSlider::sliderReleased, context, [sl, norm, &inlet, &ctx]() {
112 ctx.dispatcher.submit<SetControlValue<T>>(inlet, norm.from01(sl->value()));
113 ctx.dispatcher.commit();
114 sl->moving = false;
115 });
116 }
117
118 QObject::connect(&inlet, &T::valueChanged, sl, [sl, norm](const ossia::value& val) {
119 if constexpr(Control)
120 {
121 if(!sl->moving)
122 sl->setValue(norm.to01(ossia::convert<double>(val)));
123 }
124 else
125 {
126 sl->setValue(norm.to01(ossia::convert<double>(val)));
127 }
128 });
129
130 return sl;
131 }
132
133 template <typename T, typename Control_T>
134 static auto make_item(
135 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
136 QGraphicsItem* parent, QObject* context)
137 {
138 ConcreteNormalizer<Normalizer, T> norm{slider};
139
140 auto sl = new ControlUI{nullptr};
141 initWidgetProperties(inlet, *sl);
142 bindFloatDomain(slider, inlet, *sl);
143 sl->setValue(norm.to01(ossia::convert<double>(inlet.value())));
144
145 if constexpr(Control)
146 {
147 QObject::connect(sl, &ControlUI::sliderMoved, context, [sl, norm, &inlet, &ctx] {
148 sl->moving = true;
149 ctx.dispatcher.submit<SetControlValue<Control_T>>(
150 inlet, norm.from01(sl->value()));
151 });
152 QObject::connect(
153 sl, &ControlUI::sliderReleased, context, [sl, norm, &inlet, &ctx] {
154 ctx.dispatcher.submit<SetControlValue<Control_T>>(
155 inlet, norm.from01(sl->value()));
156 ctx.dispatcher.commit();
157 sl->moving = false;
158 });
159 }
160
161 QObject::connect(
162 &inlet, &Control_T::valueChanged, sl, [sl, norm](const ossia::value& val) {
163 if constexpr(Control)
164 {
165 if(!sl->moving)
166 sl->setValue(norm.to01(ossia::convert<double>(val)));
167 }
168 else
169 {
170 sl->setValue(norm.to01(ossia::convert<double>(val)));
171 }
172 });
173 QObject::connect(
174 &inlet, &Control_T::executionValueChanged, sl,
175 [sl, norm](const ossia::value& val) {
176 sl->setExecutionValue(norm.to01(ossia::convert<double>(val)));
177 });
178 QObject::connect(&inlet, &Control_T::executionReset, sl, &ControlUI::resetExecution);
179
180 return sl;
181 }
182};
183
190
192{
193 static Process::PortItemLayout layout() noexcept
194 {
195 return Process::DefaultControlLayouts::slider();
196 }
197
198 template <typename T>
199 static auto make_widget(
200 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
201 {
202 auto sl = new score::ValueSlider{parent};
203 sl->setOrientation(Qt::Horizontal);
204 bindIntDomain(inlet, inlet, *sl);
205 sl->setValue(ossia::convert<int>(inlet.value()));
206 sl->setContentsMargins(0, 0, 0, 0);
207
208 QObject::connect(
209 sl, &score::IntSlider::sliderMoved, context, [sl, &inlet, &ctx](int p) {
210 sl->moving = true;
211 ctx.dispatcher.submit<SetControlValue<T>>(inlet, p);
212 });
213 QObject::connect(sl, &score::IntSlider::sliderReleased, context, [sl, &inlet, &ctx] {
214 ctx.dispatcher.submit<SetControlValue<T>>(inlet, sl->value());
215 ctx.dispatcher.commit();
216 sl->moving = false;
217 });
218
219 QObject::connect(&inlet, &T::valueChanged, sl, [sl](const ossia::value& val) {
220 if(!sl->moving)
221 sl->setValue(ossia::convert<int>(val));
222 });
223
224 return sl;
225 }
226
227 template <typename T, typename Control_T>
228 static QGraphicsItem* make_item(
229 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
230 QGraphicsItem* parent, QObject* context)
231 {
232 auto sl = new score::QGraphicsIntSlider{nullptr};
233 initWidgetProperties(inlet, *sl);
234 bindIntDomain(slider, inlet, *sl);
235 sl->setValue(ossia::convert<int>(inlet.value()));
236
237 QObject::connect(
238 sl, &score::QGraphicsIntSlider::sliderMoved, context, [=, &inlet, &ctx] {
239 sl->moving = true;
240 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, sl->value());
241 });
242 QObject::connect(
243 sl, &score::QGraphicsIntSlider::sliderReleased, context, [&ctx, sl]() {
244 ctx.dispatcher.commit();
245 sl->moving = false;
246 });
247
248 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
249 if(!sl->moving)
250 sl->setValue(ossia::convert<int>(val));
251 });
252 QObject::connect(
253 &inlet, &Control_T::executionValueChanged, sl, [=](const ossia::value& val) {
254 sl->setExecutionValue(ossia::convert<int>(val));
255 });
256 QObject::connect(
257 &inlet, &Control_T::executionReset, sl,
258 &score::QGraphicsIntSlider::resetExecution);
259
260 return sl;
261 }
262};
263
265{
266 static Process::PortItemLayout layout() noexcept
267 {
268 return Process::DefaultControlLayouts::slider();
269 }
270
271 template <typename T>
272 static auto make_widget(
273 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
274 {
275 // TODO
276 return nullptr;
277 }
278
279 template <typename T, typename Control_T>
280 static QGraphicsItem* make_item(
281 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
282 QGraphicsItem* parent, QObject* context)
283 {
284 auto sl = new score::QGraphicsRangeSlider{parent};
285 initWidgetProperties(inlet, *sl);
286 bindIntDomain(slider, inlet, *sl);
287 sl->setValue(ossia::convert<ossia::vec2f>(inlet.value()));
288
289 QObject::connect(
290 sl, &score::QGraphicsRangeSlider::sliderMoved, context, [=, &inlet, &ctx] {
291 sl->moving = true;
292 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, sl->value());
293 });
294 QObject::connect(
295 sl, &score::QGraphicsRangeSlider::sliderReleased, context, [&ctx, sl]() {
296 ctx.dispatcher.commit();
297 sl->moving = false;
298 });
299
300 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
301 if(!sl->moving)
302 sl->setValue(ossia::convert<ossia::vec2f>(val));
303 });
304 QObject::connect(
305 &inlet, &Control_T::executionValueChanged, sl, [=](const ossia::value& val) {
306 // TODO
307 // sl->setExecutionValue(ossia::convert<ossia::vec2f>(val));
308 });
309 QObject::connect(
310 &inlet, &Control_T::executionReset, sl,
311 &score::QGraphicsRangeSlider::resetExecution);
312
313 return sl;
314 }
315};
317{
318 static Process::PortItemLayout layout() noexcept
319 {
320 return Process::DefaultControlLayouts::slider();
321 }
322
323 template <typename T>
324 static auto make_widget(
325 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
326 {
327 // TODO
328 return nullptr;
329 }
330
331 template <typename T, typename Control_T>
332 static QGraphicsItem* make_item(
333 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
334 QGraphicsItem* parent, QObject* context)
335 {
336 auto sl = new score::QGraphicsRangeSlider{parent};
337 initWidgetProperties(inlet, *sl);
338 bindFloatDomain(slider, inlet, *sl);
339 sl->setValue(ossia::convert<ossia::vec2f>(inlet.value()));
340
341 QObject::connect(
342 sl, &score::QGraphicsRangeSlider::sliderMoved, context, [=, &inlet, &ctx] {
343 sl->moving = true;
344 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, sl->value());
345 });
346 QObject::connect(
347 sl, &score::QGraphicsRangeSlider::sliderReleased, context, [&ctx, sl]() {
348 ctx.dispatcher.commit();
349 sl->moving = false;
350 });
351
352 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
353 if(!sl->moving)
354 sl->setValue(ossia::convert<ossia::vec2f>(val));
355 });
356 QObject::connect(
357 &inlet, &Control_T::executionValueChanged, sl, [=](const ossia::value& val) {
358 // TODO
359 // sl->setExecutionValue(ossia::convert<ossia::vec2f>(val));
360 });
361 QObject::connect(
362 &inlet, &Control_T::executionReset, sl,
363 &score::QGraphicsRangeSlider::resetExecution);
364
365 return sl;
366 }
367};
369{
370 static Process::PortItemLayout layout() noexcept
371 {
372 return Process::DefaultControlLayouts::pad();
373 }
374
375 template <typename T>
376 static auto make_widget(
377 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
378 {
379 SCORE_TODO;
380 return nullptr; // TODO
381 }
382
383 template <typename T, typename Control_T>
384 static QGraphicsItem* make_item(
385 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
386 QGraphicsItem* parent, QObject* context)
387 {
388 auto sl = new score::QGraphicsXYSpinboxChooser{true, nullptr};
389 initWidgetProperties(inlet, *sl);
390 bindVec2Domain(slider, inlet, *sl);
391 sl->setValue(
392 LinearNormalizer::to01(*sl, ossia::convert<ossia::vec2f>(inlet.value())));
393
394 QObject::connect(
395 sl, &score::QGraphicsXYSpinboxChooser::sliderMoved, context, [=, &inlet, &ctx] {
396 sl->moving = true;
397 ctx.dispatcher.submit<SetControlValue<Control_T>>(
398 inlet, LinearNormalizer::from01(*sl, sl->value()));
399 });
400 QObject::connect(
401 sl, &score::QGraphicsXYSpinboxChooser::sliderReleased, context, [&ctx, sl]() {
402 ctx.dispatcher.commit();
403 sl->moving = false;
404 });
405
406 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
407 if(!sl->moving)
408 sl->setValue(LinearNormalizer::to01(*sl, ossia::convert<ossia::vec2f>(val)));
409 });
410
411 return sl;
412 }
413};
414
416{
417 static Process::PortItemLayout layout() noexcept
418 {
419 return Process::DefaultControlLayouts::spinbox();
420 }
421
422 template <typename T>
423 static auto make_widget(
424 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
425 {
426 auto sl = new QSpinBox{parent};
427 bindIntDomain(inlet, inlet, *sl);
428 sl->setValue(ossia::convert<int>(inlet.value()));
429 sl->setContentsMargins(0, 0, 0, 0);
430
431 QObject::connect(
432 sl, SignalUtils::QSpinBox_valueChanged_int(), context, [&inlet, &ctx](int val) {
433 CommandDispatcher<>{ctx.commandStack}.submit<SetControlValue<T>>(inlet, val);
434 });
435
436 QObject::connect(&inlet, &T::valueChanged, sl, [sl](const ossia::value& val) {
437 sl->setValue(ossia::convert<int>(val));
438 });
439
440 return sl;
441 }
442
443 template <typename T, typename Control_T>
444 static QGraphicsItem* make_item(
445 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
446 QGraphicsItem* parent, QObject* context)
447 {
448 auto sl = new score::QGraphicsIntSpinbox{nullptr};
449 initWidgetProperties(inlet, *sl);
450 bindIntDomain(slider, inlet, *sl);
451 sl->setValue(ossia::convert<int>(inlet.value()));
452
453 QObject::connect(
454 sl, &score::QGraphicsIntSpinbox::sliderMoved, context, [=, &inlet, &ctx] {
455 sl->moving = true;
456 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, sl->value());
457 });
458 QObject::connect(
459 sl, &score::QGraphicsIntSpinbox::sliderReleased, context, [&ctx, sl]() {
460 ctx.dispatcher.commit();
461 sl->moving = false;
462 });
463
464 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
465 if(!sl->moving)
466 sl->setValue(ossia::convert<int>(val));
467 });
468
469 QObject::connect(
470 &inlet, &Control_T::executionValueChanged, sl, [=](const ossia::value& val) {
471 if(!sl->moving)
472 sl->setExecutionValue(ossia::convert<int>(val));
473 });
474 QObject::connect(
475 &inlet, &Control_T::executionReset, sl,
476 &score::QGraphicsIntSpinbox::resetExecution);
477
478 return sl;
479 }
480};
481
483{
484 static Process::PortItemLayout layout() noexcept
485 {
486 return Process::DefaultControlLayouts::spinbox();
487 }
488
489 template <typename T>
490 static auto make_widget(
491 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
492 {
493 auto sl = new QDoubleSpinBox{parent};
494 bindFloatDomain(inlet, inlet, *sl);
495 sl->setValue(ossia::convert<float>(inlet.value()));
496 sl->setContentsMargins(0, 0, 0, 0);
497
498 QObject::connect(
499 sl, SignalUtils::QDoubleSpinBox_valueChanged_double(), context,
500 [&inlet, &ctx](double val) {
501 CommandDispatcher<>{ctx.commandStack}.submit<SetControlValue<T>>(inlet, val);
502 });
503
504 QObject::connect(&inlet, &T::valueChanged, sl, [sl](const ossia::value& val) {
505 sl->setValue(ossia::convert<float>(val));
506 });
507
508 return sl;
509 }
510
511 template <typename T, typename Control_T>
512 static QGraphicsItem* make_item(
513 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
514 QGraphicsItem* parent, QObject* context)
515 {
516 ConcreteNormalizer<LinearNormalizer, T> norm{slider};
517
518 auto sl = new score::QGraphicsSpinbox{nullptr};
519 initWidgetProperties(inlet, *sl);
520 bindFloatDomain(slider, inlet, *sl);
521 sl->setValue(norm.to01(ossia::convert<float>(inlet.value())));
522
523 QObject::connect(
524 sl, &score::QGraphicsSpinbox::sliderMoved, context,
525 [=, &inlet, &ctx] {
526 sl->moving = true;
527 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, norm.from01(sl->value()));
528 });
529 QObject::connect(
530 sl, &score::QGraphicsSpinbox::sliderReleased, context, [&ctx, sl]() {
531 ctx.dispatcher.commit();
532 sl->moving = false;
533 });
534
535 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
536 if(!sl->moving)
537 sl->setValue(norm.to01(ossia::convert<float>(val)));
538 });
539
540 QObject::connect(
541 &inlet, &Control_T::executionValueChanged, sl, [=](const ossia::value& val) {
542 if(!sl->moving)
543 sl->setExecutionValue(norm.to01(ossia::convert<float>(val)));
544 });
545 QObject::connect(
546 &inlet, &Control_T::executionReset, sl,
547 &score::QGraphicsSpinbox::resetExecution);
548
549 return sl;
550 }
551};
552
554{
555 static Process::PortItemLayout layout() noexcept
556 {
557 using namespace Process;
558 return DefaultControlLayouts::knob();
559 }
560
561 template <typename T>
562 static auto make_widget(
563 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
564 {
565 // FIXME
566 return nullptr;
567 }
568
569 template <typename T, typename Control_T>
570 static auto make_item(
571 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
572 QGraphicsItem* parent, QObject* context)
573 {
574 auto sl = new score::QGraphicsTimeChooser{nullptr};
575 initWidgetProperties(inlet, *sl);
576 // bindFloatDomain(slider, inlet, *sl);
577 sl->setValue(ossia::convert<ossia::vec2f>(inlet.value()));
578
579 QObject::connect(
580 sl, &score::QGraphicsTimeChooser::sliderMoved, context, [sl, &inlet, &ctx] {
581 sl->knob.moving = true;
582 sl->combo.moving = true;
583 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, sl->value());
584 });
585 QObject::connect(
586 sl, &score::QGraphicsTimeChooser::sliderReleased, context, [sl, &inlet, &ctx] {
587 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, sl->value());
588 ctx.dispatcher.commit();
589 sl->knob.moving = false;
590 sl->combo.moving = false;
591 });
592
593 QObject::connect(
594 &inlet, &Control_T::valueChanged, sl, [sl](const ossia::value& val) {
595 if(!sl->knob.moving && !sl->combo.moving)
596 {
597 sl->setValue(ossia::convert<ossia::vec2f>(val));
598 }
599 });
600 QObject::connect(
601 &inlet, &Control_T::executionValueChanged, sl, [sl](const ossia::value& val) {
602 sl->setExecutionValue(ossia::convert<ossia::vec2f>(val));
603 });
604 QObject::connect(
605 &inlet, &Control_T::executionReset, sl,
606 &score::QGraphicsTimeChooser::resetExecution);
607
608 return sl;
609 }
610};
611
612struct Toggle
613{
614 static Process::PortItemLayout layout() noexcept
615 {
616 return Process::DefaultControlLayouts::toggle();
617 }
618
619 template <typename T>
620 static auto make_widget(
621 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
622 {
623 auto sl = new QCheckBox{parent};
624 sl->setChecked(ossia::convert<bool>(inlet.value()));
625 QObject::connect(sl, &QCheckBox::toggled, context, [&inlet, &ctx](bool val) {
626 CommandDispatcher<>{ctx.commandStack}.submit<SetControlValue<T>>(inlet, val);
627 });
628
629 QObject::connect(&inlet, &T::valueChanged, sl, [sl](const ossia::value& val) {
630 sl->setChecked(ossia::convert<bool>(val));
631 });
632
633 return sl;
634 }
635
636 template <typename T, typename Control_T>
637 static QGraphicsItem* make_item(
638 const T& toggle, Control_T& inlet, const score::DocumentContext& ctx,
639 QGraphicsItem* parent, QObject* context)
640 {
641 auto cb = new score::QGraphicsCheckBox{nullptr};
642 initWidgetProperties(inlet, *cb);
643 cb->setState(ossia::convert<bool>(inlet.value()));
644
645 QObject::connect(
646 cb, &score::QGraphicsCheckBox::toggled, context,
647 [=, &inlet, &ctx](bool toggled) {
648 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, toggled);
649 ctx.dispatcher.commit();
650 });
651
652 QObject::connect(
653 &inlet, &Control_T::valueChanged, cb,
654 [cb](const ossia::value& val) { cb->setState(ossia::convert<bool>(val)); });
655
656 return cb;
657 }
658};
659
661{
662 static Process::PortItemLayout layout() noexcept
663 {
664 return Process::DefaultControlLayouts::bang();
665 }
666
667 template <typename T>
668 static auto make_widget(
669 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
670 {
671 auto sl = new QPushButton{parent};
672 const auto& name = inlet.visualName();
673 sl->setText(name.isEmpty() ? QObject::tr("Bang") : name);
674 sl->setContentsMargins(0, 0, 0, 0);
675
676 auto& cinlet = const_cast<T&>(inlet);
677 QObject::connect(sl, &QPushButton::pressed, context, [&cinlet] {
678 cinlet.valueChanged(ossia::impulse{});
679 });
680
681 return sl;
682 }
683
684 template <typename T, typename Control_T>
685 static QGraphicsItem* make_item(
686 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
687 QGraphicsItem* parent, QObject* context)
688 {
689 auto toggle = new score::QGraphicsButton{nullptr};
690 initWidgetProperties(inlet, *toggle);
691
692 QObject::connect(
693 toggle, &score::QGraphicsButton::pressed, context, [=, &inlet](bool pressed) {
694 if(pressed)
695 {
696 inlet.valueChanged(ossia::impulse{});
697 }
698 });
699
700 return toggle;
701 }
702};
703
704struct Button
705{
706 static Process::PortItemLayout layout() noexcept
707 {
708 return Process::DefaultControlLayouts::bang();
709 }
710
711 template <typename T>
712 static auto make_widget(
713 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
714 {
715 auto sl = new QPushButton{parent};
716 const auto& name = inlet.visualName();
717 sl->setText(name.isEmpty() ? QObject::tr("Bang") : name);
718 sl->setContentsMargins(0, 0, 0, 0);
719
720 // TODO should we not make a command here
721 auto& cinlet = const_cast<T&>(inlet);
722 QObject::connect(
723 sl, &QPushButton::pressed, context, [&cinlet] { cinlet.setValue(true); });
724 QObject::connect(
725 sl, &QPushButton::released, context, [&cinlet] { cinlet.setValue(false); });
726
727 return sl;
728 }
729
730 template <typename T, typename Control_T>
731 static QGraphicsItem* make_item(
732 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
733 QGraphicsItem* parent, QObject* context)
734 {
735 auto toggle = new score::QGraphicsButton{nullptr};
736 initWidgetProperties(inlet, *toggle);
737
738 QObject::connect(
739 toggle, &score::QGraphicsButton::pressed, context,
740 [=, &inlet, &ctx](bool pressed) {
741 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, pressed);
742 ctx.dispatcher.commit();
743 });
744
745 return toggle;
746 }
747};
748
750{
751 static Process::PortItemLayout layout() noexcept
752 {
753 return Process::DefaultControlLayouts::chooser_toggle();
754 }
755
756 template <typename T>
757 static constexpr auto getAlternatives(const T& t) -> decltype(auto)
758 {
759 if constexpr(std::is_member_function_pointer_v<decltype(&T::alternatives)>)
760 {
761 return t.alternatives();
762 }
763 else
764 {
765 return t.alternatives;
766 }
767 }
768
769 template <typename T>
770 static auto make_widget(
771 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
772 {
773
774 const auto& alts = getAlternatives(inlet);
775 SCORE_ASSERT(alts.size() == 2);
776 auto toggleBtn = new score::ToggleButton{alts, parent};
777 toggleBtn->setCheckable(true);
778 bool b = ossia::convert<bool>(inlet.value());
779 if(b && !toggleBtn->isChecked())
780 toggleBtn->toggle();
781 else if(!b && toggleBtn->isChecked())
782 toggleBtn->toggle();
783
784 QObject::connect(
785 toggleBtn, &score::ToggleButton::toggled, context, [&inlet, &ctx](bool val) {
786 CommandDispatcher<>{ctx.commandStack}.submit<SetControlValue<T>>(inlet, val);
787 });
788
789 QObject::connect(
790 &inlet, &T::valueChanged, toggleBtn, [toggleBtn](const ossia::value& val) {
791 bool b = ossia::convert<bool>(val);
792 if(b && !toggleBtn->isChecked())
793 toggleBtn->toggle();
794 else if(!b && toggleBtn->isChecked())
795 toggleBtn->toggle();
796 });
797
798 return toggleBtn;
799 }
800
801 template <typename T, typename Control_T>
802 static QGraphicsItem* make_item(
803 const T& control, Control_T& inlet, const score::DocumentContext& ctx,
804 QGraphicsItem* parent, QObject* context)
805 {
806 const auto& alts = getAlternatives(control);
807 SCORE_ASSERT(alts.size() == 2);
808 auto toggle = new score::QGraphicsToggle{alts[0], alts[1], nullptr};
809 initWidgetProperties(inlet, *toggle);
810 toggle->setState(ossia::convert<bool>(inlet.value()));
811
812 QObject::connect(
813 toggle, &score::QGraphicsToggle::toggled, context,
814 [=, &inlet, &ctx](bool toggled) {
815 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, toggled);
816 ctx.dispatcher.commit();
817 });
818
819 QObject::connect(
820 &inlet, &Control_T::valueChanged, toggle, [toggle](const ossia::value& val) {
821 toggle->setState(ossia::convert<bool>(val));
822 });
823
824 return toggle;
825 }
826};
827
829{
830 static Process::PortItemLayout layout() noexcept
831 {
832 return Process::DefaultControlLayouts::lineedit();
833 }
834
835 template <typename T>
836 static auto make_widget(
837 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
838 {
839 auto sl = new QLineEdit{parent};
840 sl->setText(QString::fromStdString(ossia::convert<std::string>(inlet.value())));
841 sl->setContentsMargins(0, 0, 0, 0);
842 sl->setMaximumWidth(70);
843 QObject::connect(sl, &QLineEdit::editingFinished, context, [sl, &inlet, &ctx]() {
844 CommandDispatcher<>{ctx.commandStack}.submit<SetControlValue<T>>(
845 inlet, sl->text().toStdString());
846 });
847
848 QObject::connect(&inlet, &T::valueChanged, sl, [sl](const ossia::value& val) {
849 sl->setText(QString::fromStdString(ossia::convert<std::string>(val)));
850 });
851
852 return sl;
853 }
854
855 template <typename T, typename Control_T>
856 static score::QGraphicsLineEdit* make_item(
857 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
858 QGraphicsItem* parent, QObject* context)
859 {
860 auto sl = new score::QGraphicsLineEdit{parent};
861 initWidgetProperties(inlet, *sl);
862 sl->setTextWidth(180.);
863 sl->setDefaultTextColor(QColor{"#E0B01E"});
864 sl->setCursor(Qt::IBeamCursor);
865
866 sl->setPlainText(QString::fromStdString(ossia::convert<std::string>(inlet.value())));
867
868 auto doc = sl->document();
869 auto on_edit = [=, &inlet, &ctx] {
870 auto cur_str = ossia::convert<std::string>(inlet.value());
871 if(cur_str != doc->toPlainText().toStdString())
872 {
873 CommandDispatcher<>{ctx.commandStack}.submit<SetControlValue<Control_T>>(
874 inlet, doc->toPlainText().toStdString());
875 }
876 };
877
878 if(!inlet.noValueChangeOnMove)
879 {
880 QObject::connect(doc, &QTextDocument::contentsChanged, context, on_edit);
881 }
882 else
883 {
884 QObject::connect(sl, &score::QGraphicsLineEdit::editingFinished, context, on_edit);
885 }
886
887 if(auto obj = dynamic_cast<score::ResizeableItem*>(context))
888 {
889 QObject::connect(
890 sl, &score::QGraphicsLineEdit::sizeChanged, obj,
891 &score::ResizeableItem::childrenSizeChanged);
892 }
893
894 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
895 auto str = QString::fromStdString(ossia::convert<std::string>(val));
896 if(str != doc->toPlainText())
897 doc->setPlainText(str);
898 });
899
900 return sl;
901 }
902};
903
905{
907 std::string_view language, const Process::ControlInlet& port,
908 const score::DocumentContext& ctx, QWidget* parent)
909 : ScriptDialog{language, ctx, parent}
910 , m_port{port}
911 {
912 this->setText(QString::fromStdString(ossia::convert<std::string>(port.value())));
914 &QWidget::deleteLater);
915 }
916
917 void on_accepted() override
918 {
919 this->setError(0, QString{});
920 auto cur = ossia::convert<std::string>(m_port.value());
921 auto next = this->text().toStdString();
922 if(next != cur)
923 {
924 ossia::qt::run_async(
925 qApp, [&ctx = m_context.commandStack, port = QPointer{&m_port}, next] {
926 if(port)
927 {
928 CommandDispatcher<>{ctx}.submit(new Process::SetControlValue{*port, next});
929 }
930 });
931 }
932 }
933
934 const Process::ControlInlet& m_port;
935};
936
938{
939 static Process::PortItemLayout layout() noexcept
940 {
941 return Process::DefaultControlLayouts::lineedit();
942 }
943
944 template <typename T>
945 static auto make_widget(
946 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
947 {
948 auto toggle = new QPushButton{QObject::tr("Edit..."), parent};
949 QObject::connect(toggle, &QPushButton::clicked, context, [=, &inlet, &ctx] {
950 createDialog(inlet, ctx);
951 });
952 return toggle;
953 }
954
955 template <typename T, typename Control_T>
956 static auto make_item(
957 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
958 QGraphicsItem* parent, QObject* context)
959 {
960 auto toggle = new score::QGraphicsTextButton{QObject::tr("Edit..."), nullptr};
961 initWidgetProperties(inlet, *toggle);
962
963 QObject::connect(
964 toggle, &score::QGraphicsTextButton::pressed, context,
965 [=, &inlet, &ctx] { createDialog(inlet, ctx); }, Qt::QueuedConnection);
966
967 return toggle;
968 }
969
970 static void
971 createDialog(const Process::ProgramEdit& inlet, const score::DocumentContext& ctx)
972 {
973 auto dial = new ProgramPortScriptDialog{inlet.language, inlet, ctx, nullptr};
974 dial->exec();
975 }
976};
977
979{
980 static Process::PortItemLayout layout() noexcept
981 {
982 return Process::DefaultControlLayouts::lineedit();
983 }
984 template <typename T>
985 static auto make_widget(
986 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
987 {
988 auto sl = new QLineEdit{parent};
989 auto act = new QAction{sl};
990
991 score::setHelp(act, QObject::tr("Opening a File"));
992 act->setIcon(QIcon(":/icons/search.png"));
993 sl->setPlaceholderText(QObject::tr("Open File"));
994 auto on_open = [=, &inlet] {
995 auto filename
996 = QFileDialog::getOpenFileName(nullptr, "Open File", {}, inlet.filters());
997 if(filename.isEmpty())
998 return;
999 sl->setText(filename);
1000 };
1001
1002 QObject::connect(sl, &QLineEdit::returnPressed, on_open);
1003 QObject::connect(act, &QAction::triggered, on_open);
1004 sl->addAction(act, QLineEdit::TrailingPosition);
1005
1006 sl->setText(QString::fromStdString(ossia::convert<std::string>(inlet.value())));
1007 sl->setContentsMargins(0, 0, 0, 0);
1008 //sl->setMaximumWidth(70);
1009
1010 QObject::connect(sl, &QLineEdit::editingFinished, context, [sl, &inlet, &ctx]() {
1011 CommandDispatcher<>{ctx.commandStack}.submit<SetControlValue<T>>(
1012 inlet, sl->text().toStdString());
1013 });
1014 QObject::connect(&inlet, &T::valueChanged, sl, [sl](const ossia::value& val) {
1015 sl->setText(QString::fromStdString(ossia::convert<std::string>(val)));
1016 });
1017 return sl;
1018 }
1019
1020 template <typename T, typename Control_T>
1021 static score::QGraphicsTextButton* make_item(
1022 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
1023 QGraphicsItem* parent, QObject* context)
1024 {
1025 auto bt = new score::QGraphicsTextButton{"Choose a file...", parent};
1026 initWidgetProperties(inlet, *bt);
1027 auto on_open = [&inlet, &ctx] {
1028 auto filename
1029 = QFileDialog::getOpenFileName(nullptr, "Open File", {}, inlet.filters());
1030 if(filename.isEmpty())
1031 return;
1032
1033 CommandDispatcher<>{ctx.commandStack}.submit<SetControlValue<Control_T>>(
1034 inlet, filename.toStdString());
1035 };
1036 auto on_set = [&inlet, &ctx](const QString& filename) {
1037 if(filename.isEmpty())
1038 return;
1039
1040 CommandDispatcher<>{ctx.commandStack}.submit<SetControlValue<Control_T>>(
1041 inlet, filename.toStdString());
1042 };
1043 QObject::connect(
1044 bt, &score::QGraphicsTextButton::pressed, &inlet, on_open, Qt::QueuedConnection);
1045 QObject::connect(
1046 bt, &score::QGraphicsTextButton::dropped, &inlet, on_set, Qt::QueuedConnection);
1047 auto set = [=](const ossia::value& val) {
1048 auto str = QString::fromStdString(ossia::convert<std::string>(val));
1049 if(str != bt->text())
1050 {
1051 if(!str.isEmpty())
1052 bt->setText(str.split("/").back());
1053 else
1054 bt->setText("Choose a file...");
1055 }
1056 };
1057
1058 set(slider.value());
1059 QObject::connect(&inlet, &Control_T::valueChanged, bt, set);
1060
1061 return bt;
1062 }
1063};
1064
1065struct Enum
1066{
1067 static Process::PortItemLayout layout() noexcept
1068 {
1069 return Process::DefaultControlLayouts::list();
1070 }
1071
1072 static const auto& toStd(const char* const& s) { return s; }
1073 static const auto& toStd(const std::string& s) { return s; }
1074 static auto toStd(const QString& s) { return s.toStdString(); }
1075
1076 static const auto& convert(const std::string& str, const char*) { return str; }
1077 static auto convert(const std::string& str, const QString&)
1078 {
1079 return QString::fromStdString(str);
1080 }
1081 template <typename T>
1082 static auto make_widget(
1083 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
1084 {
1085 const auto& values = inlet.getValues();
1086 using val_t = std::remove_reference_t<decltype(values[0])>;
1087 auto sl = new QComboBox{parent};
1088 for(const auto& e : values)
1089 {
1090 sl->addItem(e);
1091 }
1092
1093 auto set_index = [values, sl](const ossia::value& val) {
1094 auto v = ossia::convert<std::string>(val);
1095 auto it = ossia::find(values, convert(v, val_t{}));
1096 if(it != values.end())
1097 {
1098 sl->setCurrentIndex(std::distance(values.begin(), it));
1099 }
1100 };
1101 set_index(inlet.value());
1102
1103 QObject::connect(
1104 sl, SignalUtils::QComboBox_currentIndexChanged_int(), context,
1105 [values, &inlet, &ctx](int idx) {
1106 CommandDispatcher<>{ctx.commandStack}.submit<SetControlValue<T>>(
1107 inlet, toStd(values[idx]));
1108 });
1109
1110 QObject::connect(
1111 &inlet, &T::valueChanged, sl, [=](const ossia::value& val) { set_index(val); });
1112
1113 return sl;
1114 }
1115
1116 template <typename T, typename Control_T>
1117 static auto make_item(
1118 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
1119 QGraphicsItem* parent, QObject* context)
1120 {
1121 const auto& values = slider.getValues();
1122 using val_t = std::remove_reference_t<decltype(values[0])>;
1123
1124 auto sl = slider.pixmaps.empty() || slider.pixmaps[0] == nullptr
1125 ? new score::QGraphicsEnum{values, nullptr}
1127 values, slider.pixmaps, nullptr};
1128
1129 initWidgetProperties(inlet, *sl);
1130
1131 auto set_index = [values, sl](const ossia::value& val) {
1132 auto v = ossia::convert<std::string>(val);
1133 auto it = ossia::find(values, convert(v, val_t{}));
1134 if(it != values.end())
1135 {
1136 sl->setValue(std::distance(values.begin(), it));
1137 }
1138 };
1139
1140 set_index(inlet.value());
1141
1142 QObject::connect(
1143 sl, &score::QGraphicsEnum::currentIndexChanged, context,
1144 [sl, &inlet, &ctx](int idx) {
1145 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, toStd(sl->array[idx]));
1146 ctx.dispatcher.commit();
1147 });
1148
1149 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
1150 set_index(val);
1151 });
1152
1153 return sl;
1154 }
1155};
1156
1158{
1159 static Process::PortItemLayout layout() noexcept
1160 {
1161 return Process::DefaultControlLayouts::combo();
1162 }
1163
1164 template <typename T>
1165 static auto make_widget(
1166 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
1167 {
1168 const auto& values = inlet.getValues();
1169 auto sl = new score::ComboBox{parent};
1170 for(auto& e : values)
1171 {
1172 sl->addItem(e.first);
1173 }
1174 sl->setContentsMargins(0, 0, 0, 0);
1175
1176 auto set_index = [values, sl](const ossia::value& val) {
1177 auto it
1178 = ossia::find_if(values, [&](const auto& pair) { return pair.second == val; });
1179 if(it != values.end())
1180 {
1181 sl->setCurrentIndex(std::distance(values.begin(), it));
1182 }
1183 };
1184 set_index(inlet.value());
1185
1186 QObject::connect(
1187 sl, SignalUtils::QComboBox_currentIndexChanged_int(), context,
1188 [values, &inlet, &ctx](int idx) {
1189 CommandDispatcher<>{ctx.commandStack}.submit<SetControlValue<T>>(
1190 inlet, values[idx].second);
1191 });
1192
1193 QObject::connect(
1194 &inlet, &T::valueChanged, sl, [=](const ossia::value& val) { set_index(val); });
1195
1196 return sl;
1197 }
1198
1199 template <typename U, typename Control_T>
1200 static QGraphicsItem* make_item(
1201 const U& slider, Control_T& inlet, const score::DocumentContext& ctx,
1202 QGraphicsItem* parent, QObject* context)
1203 {
1204 const auto N = slider.count();
1205
1206 const auto& values = slider.getValues();
1207 QStringList arr;
1208 arr.reserve(N);
1209 for(std::size_t i = 0; i < N; i++)
1210 arr.push_back(values[i].first);
1211
1212 auto sl = new score::QGraphicsCombo{arr, nullptr};
1213 initWidgetProperties(inlet, *sl);
1214
1215 auto set_index = [values, sl](const ossia::value& val) {
1216 auto it
1217 = ossia::find_if(values, [&](const auto& pair) { return pair.second == val; });
1218 if(it != values.end())
1219 {
1220 sl->setValue(std::distance(values.begin(), it));
1221 }
1222 };
1223 set_index(inlet.value());
1224
1225 QObject::connect(
1226 sl, &score::QGraphicsCombo::sliderMoved, context, [values, sl, &inlet, &ctx] {
1227 sl->moving = true;
1228 ctx.dispatcher.submit<SetControlValue<Control_T>>(
1229 inlet, values[sl->value()].second);
1230 });
1231 QObject::connect(sl, &score::QGraphicsCombo::sliderReleased, context, [sl, &ctx] {
1232 ctx.dispatcher.commit();
1233 sl->moving = false;
1234 });
1235
1236 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
1237 if(sl->moving)
1238 return;
1239
1240 set_index(val);
1241 });
1242
1243 return sl;
1244 }
1245};
1246
1247struct TimeSignatureValidator final : public QValidator
1248{
1249 static constexpr Process::PortItemLayout layout() noexcept
1250 {
1251 using namespace Process;
1252 return PortItemLayout{};
1253 }
1254
1255 using QValidator::QValidator;
1256 State validate(QString& str, int&) const override
1257 {
1258 auto p = ossia::get_time_signature(str.toStdString());
1259 if(!p)
1260 return State::Invalid;
1261
1262 return State::Acceptable;
1263 }
1264};
1265
1267{
1268 static Process::PortItemLayout layout() noexcept
1269 {
1270 return Process::DefaultControlLayouts::pad();
1271 }
1272
1273 template <typename T>
1274 static auto make_widget(
1275 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
1276 {
1277 SCORE_TODO;
1278 return nullptr; // TODO
1279 }
1280
1281 template <typename T, typename Control_T>
1282 static QGraphicsItem* make_item(
1283 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
1284 QGraphicsItem* parent, QObject* context)
1285 {
1286 auto sl = new score::QGraphicsHSVChooser{nullptr};
1287 initWidgetProperties(inlet, *sl);
1288 sl->setRgbaValue(ossia::convert<ossia::vec4f>(inlet.value()));
1289
1290 QObject::connect(
1291 sl, &score::QGraphicsHSVChooser::sliderMoved, context, [=, &inlet, &ctx] {
1292 sl->moving = true;
1293 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, sl->rgbaValue());
1294 });
1295 QObject::connect(
1296 sl, &score::QGraphicsHSVChooser::sliderReleased, context, [&ctx, sl]() {
1297 ctx.dispatcher.commit();
1298 sl->moving = false;
1299 });
1300
1301 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
1302 if(!sl->moving)
1303 sl->setRgbaValue(ossia::convert<ossia::vec4f>(val));
1304 });
1305
1306 return sl;
1307 }
1308};
1309
1311{
1312 static constexpr Process::PortItemLayout layout() noexcept
1313 {
1314 using namespace Process;
1315 return PortItemLayout{};
1316 }
1317
1318 template <typename T>
1319 static auto make_widget(
1320 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
1321 {
1322 SCORE_TODO;
1323 return nullptr; // TODO
1324 }
1325
1326 template <typename T, typename Control_T>
1327 static QGraphicsItem* make_item(
1328 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
1329 QGraphicsItem* parent, QObject* context)
1330 {
1331 auto sl = new score::QGraphicsXYChooser{nullptr};
1332 initWidgetProperties(inlet, *sl);
1333 sl->setValue(ossia::convert<ossia::vec2f>(inlet.value()));
1334 bindVec2Domain(slider, inlet, *sl);
1335
1336 QObject::connect(
1337 sl, &score::QGraphicsXYChooser::sliderMoved, context, [=, &inlet, &ctx] {
1338 sl->moving = true;
1339 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, sl->value());
1340 });
1341 QObject::connect(
1342 sl, &score::QGraphicsXYChooser::sliderReleased, context, [&ctx, sl]() {
1343 ctx.dispatcher.commit();
1344 sl->moving = false;
1345 });
1346
1347 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
1348 if(!sl->moving)
1349 sl->setValue(ossia::convert<ossia::vec2f>(val));
1350 });
1351
1352 return sl;
1353 }
1354};
1355
1357{
1358 static Process::PortItemLayout layout() noexcept
1359 {
1360 return Process::DefaultControlLayouts::pad();
1361 }
1362
1363 template <typename T>
1364 static auto make_widget(
1365 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
1366 {
1367 SCORE_TODO;
1368 return nullptr; // TODO
1369 }
1370
1371 template <typename T, typename Control_T>
1372 static QGraphicsItem* make_item(
1373 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
1374 QGraphicsItem* parent, QObject* context)
1375 {
1376 auto sl = new score::QGraphicsXYZChooser{nullptr};
1377 initWidgetProperties(inlet, *sl);
1378 sl->setValue(ossia::convert<ossia::vec3f>(inlet.value()));
1379 bindVec3Domain(slider, inlet, *sl);
1380
1381 QObject::connect(
1382 sl, &score::QGraphicsXYZChooser::sliderMoved, context, [=, &inlet, &ctx] {
1383 sl->moving = true;
1384 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, sl->value());
1385 });
1386 QObject::connect(
1387 sl, &score::QGraphicsXYZChooser::sliderReleased, context, [&ctx, sl]() {
1388 ctx.dispatcher.commit();
1389 sl->moving = false;
1390 });
1391
1392 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
1393 if(!sl->moving)
1394 sl->setValue(ossia::convert<ossia::vec3f>(val));
1395 });
1396
1397 return sl;
1398 }
1399};
1400
1402{
1403 static Process::PortItemLayout layout() noexcept
1404 {
1405 return Process::DefaultControlLayouts::pad();
1406 }
1407
1408 template <typename T>
1409 static auto make_widget(
1410 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
1411 {
1412 SCORE_TODO;
1413 return nullptr; // TODO
1414 }
1415
1416 static QGraphicsItem* make_item(
1417 const Process::XYSpinboxes& slider, Process::XYSpinboxes& inlet,
1418 const score::DocumentContext& ctx, QGraphicsItem* parent, QObject* context)
1419 {
1420 using Control_T = Process::XYSpinboxes;
1421 if(slider.integral)
1422 {
1423 auto sl = new score::QGraphicsIntXYSpinboxChooser{false, nullptr};
1424 initWidgetProperties(inlet, *sl);
1425 bindVec2Domain(slider, inlet, *sl);
1426 sl->setValue(ossia::convert<ossia::vec2f>(inlet.value()));
1427
1428 QObject::connect(
1429 sl, &score::QGraphicsIntXYSpinboxChooser::sliderMoved, context,
1430 [=, &inlet, &ctx] {
1431 sl->moving = true;
1432 auto [x, y] = sl->value();
1433 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, ossia::make_vec(x, y));
1434 });
1435 QObject::connect(
1436 sl, &score::QGraphicsIntXYSpinboxChooser::sliderReleased, context,
1437 [&ctx, sl]() {
1438 ctx.dispatcher.commit();
1439 sl->moving = false;
1440 });
1441
1442 QObject::connect(
1443 &inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
1444 if(!sl->moving)
1445 sl->setValue(ossia::convert<ossia::vec2f>(val));
1446 });
1447
1448 return sl;
1449 }
1450 else
1451 {
1452 auto sl = new score::QGraphicsXYSpinboxChooser{false, nullptr};
1453 initWidgetProperties(inlet, *sl);
1454 bindVec2Domain(slider, inlet, *sl);
1455 sl->setValue(
1456 LinearNormalizer::to01(*sl, ossia::convert<ossia::vec2f>(inlet.value())));
1457
1458 QObject::connect(
1459 sl, &score::QGraphicsXYSpinboxChooser::sliderMoved, context,
1460 [=, &inlet, &ctx] {
1461 sl->moving = true;
1462 ctx.dispatcher.submit<SetControlValue<Control_T>>(
1463 inlet, LinearNormalizer::from01(*sl, sl->value()));
1464 });
1465 QObject::connect(
1466 sl, &score::QGraphicsXYSpinboxChooser::sliderReleased, context, [&ctx, sl]() {
1467 ctx.dispatcher.commit();
1468 sl->moving = false;
1469 });
1470
1471 QObject::connect(
1472 &inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
1473 if(!sl->moving)
1474 sl->setValue(LinearNormalizer::to01(*sl, ossia::convert<ossia::vec2f>(val)));
1475 });
1476
1477 return sl;
1478 }
1479 }
1480};
1481
1483{
1484 static Process::PortItemLayout layout() noexcept
1485 {
1486 return Process::DefaultControlLayouts::pad();
1487 }
1488
1489 template <typename T>
1490 static auto make_widget(
1491 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
1492 {
1493 SCORE_TODO;
1494 return nullptr; // TODO
1495 }
1496
1497 template <typename T, typename Control_T>
1498 static QGraphicsItem* make_item(
1499 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
1500 QGraphicsItem* parent, QObject* context)
1501 {
1502 auto sl = new score::QGraphicsXYZSpinboxChooser{nullptr};
1503 initWidgetProperties(inlet, *sl);
1504 bindVec3Domain(slider, inlet, *sl);
1505 sl->setValue(
1506 LinearNormalizer::to01(*sl, ossia::convert<ossia::vec3f>(inlet.value())));
1507
1508 QObject::connect(
1509 sl, &score::QGraphicsXYZSpinboxChooser::sliderMoved, context, [=, &inlet, &ctx] {
1510 sl->moving = true;
1511 ctx.dispatcher.submit<SetControlValue<Control_T>>(
1512 inlet, LinearNormalizer::from01(*sl, sl->value()));
1513 });
1514 QObject::connect(
1515 sl, &score::QGraphicsXYZSpinboxChooser::sliderReleased, context, [&ctx, sl]() {
1516 ctx.dispatcher.commit();
1517 sl->moving = false;
1518 });
1519
1520 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
1521 if(!sl->moving)
1522 sl->setValue(LinearNormalizer::to01(*sl, ossia::convert<ossia::vec3f>(val)));
1523 });
1524
1525 return sl;
1526 }
1527};
1528
1530{
1531 static Process::PortItemLayout layout() noexcept
1532 {
1533 return Process::DefaultControlLayouts::slider();
1534 }
1535
1536 template <typename T>
1537 static auto make_widget(
1538 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
1539 {
1540 SCORE_TODO;
1541 return nullptr; // TODO
1542 }
1543
1544 template <typename T, typename Control_T>
1545 static QGraphicsItem* make_item(
1546 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
1547 QGraphicsItem* parent, QObject* context)
1548 {
1549 auto sl = new score::QGraphicsMultiSlider{nullptr};
1550 initWidgetProperties(inlet, *sl);
1551 sl->setValue(inlet.value());
1552 sl->setRange(inlet.domain());
1553
1554 QObject::connect(
1555 sl, &score::QGraphicsMultiSlider::sliderMoved, context, [=, &inlet, &ctx] {
1556 sl->moving = true;
1557 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, sl->value());
1558 });
1559 QObject::connect(
1560 sl, &score::QGraphicsMultiSlider::sliderReleased, context, [&ctx, sl]() {
1561 ctx.dispatcher.commit();
1562 sl->moving = false;
1563 });
1564
1565 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
1566 if(!sl->moving)
1567 sl->setValue(std::move(val));
1568 });
1569
1570 return sl;
1571 }
1572};
1573
1575{
1576 static Process::PortItemLayout layout() noexcept
1577 {
1578 return Process::DefaultControlLayouts::slider();
1579 }
1580
1581 template <typename T>
1582 static auto make_widget(
1583 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
1584 {
1585 SCORE_TODO;
1586 return nullptr; // TODO
1587 }
1588
1589 template <typename T, typename Control_T>
1590 static QGraphicsItem* make_item(
1591 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
1592 QGraphicsItem* parent, QObject* context)
1593 {
1594 auto sl = new score::QGraphicsMultiSliderXY{nullptr};
1595 initWidgetProperties(inlet, *sl);
1596 sl->setValue(inlet.value());
1597 sl->setRange(inlet.domain());
1598
1599 QObject::connect(
1600 sl, &score::QGraphicsMultiSliderXY::sliderMoved, context, [=, &inlet, &ctx] {
1601 sl->moving = true;
1602 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, sl->value());
1603 });
1604 QObject::connect(
1605 sl, &score::QGraphicsMultiSliderXY::sliderReleased, context, [&ctx, sl]() {
1606 ctx.dispatcher.commit();
1607 sl->moving = false;
1608 });
1609
1610 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
1611 if(!sl->moving)
1612 sl->setValue(std::move(val));
1613 });
1614
1615 return sl;
1616 }
1617};
1618
1620{
1621 static Process::PortItemLayout layout() noexcept
1622 {
1623 return Process::DefaultControlLayouts::slider();
1624 }
1625
1626 template <typename T>
1627 static auto make_widget(
1628 T& inlet, const score::DocumentContext& ctx, QWidget* parent, QObject* context)
1629 {
1630 SCORE_TODO;
1631 return nullptr; // TODO
1632 }
1633
1634 template <typename T, typename Control_T>
1635 static QGraphicsItem* make_item(
1636 const T& slider, Control_T& inlet, const score::DocumentContext& ctx,
1637 QGraphicsItem* parent, QObject* context)
1638 {
1639 auto sl = new score::QGraphicsPathGeneratorXY{nullptr};
1640 initWidgetProperties(inlet, *sl);
1641 sl->setValue(inlet.value());
1642 sl->setRange(inlet.domain());
1643
1644 QObject::connect(
1645 sl, &score::QGraphicsPathGeneratorXY::sliderMoved, context, [=, &inlet, &ctx] {
1646 sl->moving = true;
1647 ctx.dispatcher.submit<SetControlValue<Control_T>>(inlet, sl->value());
1648 });
1649 QObject::connect(
1650 sl, &score::QGraphicsPathGeneratorXY::sliderReleased, context, [&ctx, sl]() {
1651 ctx.dispatcher.commit();
1652 sl->moving = false;
1653 });
1654
1655 QObject::connect(&inlet, &Control_T::valueChanged, sl, [=](const ossia::value& val) {
1656 if(!sl->moving)
1657 sl->setValue(std::move(val));
1658 });
1659
1660 return sl;
1661 }
1662};
1663
1664
1666using Bargraph = FloatDisplay;
1667}
The CommandDispatcher class.
Definition CommandDispatcher.hpp:13
void identified_object_destroying(IdentifiedObjectAbstract *o)
To be called by subclasses.
void submit(Args &&... args)
Definition OngoingCommandDispatcher.hpp:37
void commit()
Definition OngoingCommandDispatcher.hpp:61
Definition Port.hpp:203
Definition ScriptEditor.hpp:21
Definition SetControlValue.hpp:34
Definition SetControlValue.hpp:13
Definition ComboBox.hpp:10
Definition QGraphicsButton.hpp:16
Definition QGraphicsCheckBox.hpp:16
Definition QGraphicsCombo.hpp:18
Definition QGraphicsEnum.hpp:17
Definition QGraphicsHSVChooser.hpp:18
Definition QGraphicsIntSlider.hpp:17
Definition QGraphicsSpinbox.hpp:64
Definition QGraphicsXYSpinbox.hpp:60
Definition QGraphicsMultiSlider.hpp:24
Definition QGraphicsMultiSliderXY.hpp:29
Definition QGraphicsPathGeneratorXY.hpp:29
Definition QGraphicsPixmapEnum.hpp:17
Definition QGraphicsRangeSlider.hpp:21
Definition QGraphicsSpinbox.hpp:15
Definition QGraphicsTextButton.hpp:16
Definition QGraphicsTimeChooser.hpp:21
Definition QGraphicsToggle.hpp:16
Definition QGraphicsXYChooser.hpp:18
Definition QGraphicsXYSpinbox.hpp:20
Definition QGraphicsXYZChooser.hpp:19
Definition QGraphicsXYZSpinbox.hpp:19
Definition RectItem.hpp:12
Base classes and tools to implement processes and layers.
Definition JSONVisitor.hpp:1115
Utilities for OSSIA data structures.
Definition DeviceInterface.hpp:33
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:44
Definition Port.hpp:90
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:705
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:750
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:1158
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:1066
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:979
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:74
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:317
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:369
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:483
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:1267
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:661
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:265
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:192
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:416
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:829
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:1530
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:1575
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:1620
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:938
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:905
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:554
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:1248
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:613
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:1311
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:1402
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:1357
Definition plugins/score-lib-process/Process/Dataflow/ControlWidgets.hpp:1483
Definition DocumentContext.hpp:18
Definition QGraphicsLineEdit.hpp:17
Definition lib/score/widgets/ControlWidgets.hpp:13
Definition lib/score/widgets/ControlWidgets.hpp:72
Definition lib/score/widgets/ControlWidgets.hpp:29