VecWidgets.hpp
1 #pragma once
2 #include <State/Value.hpp>
3 
4 #include <score/widgets/MarginLess.hpp>
5 #include <score/widgets/SignalUtils.hpp>
6 #include <score/widgets/TextLabel.hpp>
7 
8 #include <ossia/network/domain/domain.hpp>
9 
10 #include <QDoubleSpinBox>
11 #include <QFormLayout>
12 #include <QHBoxLayout>
13 #include <QWidget>
14 
15 #include <verdigris>
16 
17 namespace State
18 {
19 struct SCORE_LIB_STATE_EXPORT VecEditBase : public QWidget
20 {
21  W_OBJECT(VecEditBase)
22 public:
23  using QWidget::QWidget;
24 
25 public:
26  void changed() E_SIGNAL(SCORE_LIB_STATE_EXPORT, changed)
27 };
28 
29 template <std::size_t N>
30 class VecWidget final : public VecEditBase
31 {
32 public:
33  VecWidget(QWidget* parent)
34  : VecEditBase{parent}
35  {
36  auto lay = new QHBoxLayout;
37  this->setLayout(lay);
38 
39  for(std::size_t i = 0; i < N; i++)
40  {
41  auto box = new QDoubleSpinBox{this};
42  box->setMinimum(-9999);
43  box->setMaximum(9999);
44  box->setValue(0);
45 
46  connect(box, &QDoubleSpinBox::editingFinished, this, [this] { changed(); });
47 
48  lay->addWidget(box);
49  m_boxes[i] = box;
50  }
51  }
52 
53  void setValue(std::array<float, N> v)
54  {
55  for(std::size_t i = 0; i < N; i++)
56  {
57  m_boxes[i]->setValue(v[i]);
58  }
59  }
60 
61  std::array<float, N> value() const
62  {
63  std::array<float, N> v;
64  for(std::size_t i = 0; i < N; i++)
65  {
66  v[i] = m_boxes[i]->value();
67  }
68  return v;
69  }
70 
71 private:
72  std::array<QDoubleSpinBox*, N> m_boxes;
73 };
74 
75 using Vec2DEdit = VecWidget<2>;
76 using Vec3DEdit = VecWidget<3>;
77 using Vec4DEdit = VecWidget<4>;
78 
79 template <std::size_t N>
80 class VecDomainWidget final : public QWidget
81 {
82 public:
83  using domain_type = ossia::vecf_domain<N>;
84  using set_type = ossia::flat_set<float>;
85 
86  VecDomainWidget(QWidget* parent)
87  : QWidget{parent}
88  {
89  auto lay = new score::MarginLess<QFormLayout>{this};
90  this->setLayout(lay);
91 
92  auto min_l = new TextLabel{tr("Min"), this};
93  min_l->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
94  m_min = new VecWidget<N>{this};
95  auto max_l = new TextLabel{tr("Max"), this};
96  max_l->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
97  m_max = new VecWidget<N>{this};
98  lay->addWidget(min_l);
99  lay->addWidget(m_min);
100  lay->addWidget(max_l);
101  lay->addWidget(m_max);
102  }
103 
104  static std::array<std::optional<float>, N> toOptional(const std::array<float, N>& f)
105  {
106  std::array<std::optional<float>, N> res;
107  for(std::size_t i = 0; i < N; i++)
108  {
109  res[i] = f[i];
110  }
111  return res;
112  }
113 
114  static std::array<float, N> fromOptional(const std::array<std::optional<float>, N>& f)
115  {
116  std::array<float, N> res;
117  for(std::size_t i = 0; i < N; i++)
118  {
119  res[i] = f[i] ? *f[i] : 0;
120  }
121  return res;
122  }
123 
124  domain_type domain() const
125  {
126  domain_type dom;
127 
128  dom.min = toOptional(m_min->value());
129  dom.max = toOptional(m_max->value());
130 
131  return dom;
132  }
133 
134  void set_domain(ossia::domain dom_base)
135  {
136  m_min->setValue(ossia::fill_vec<N>(0));
137  m_max->setValue(ossia::fill_vec<N>(1));
138 
139  if(auto dom_p = dom_base.v.target<domain_type>())
140  {
141  auto& dom = *dom_p;
142 
143  m_min->setValue(fromOptional(dom.min));
144  m_max->setValue(fromOptional(dom.max));
145  }
146  }
147 
148 private:
149  VecWidget<N>* m_min{};
150  VecWidget<N>* m_max{};
151 };
152 }
Definition: VecWidgets.hpp:81
Definition: VecWidgets.hpp:31
Definition: TextLabel.hpp:6
Utilities for OSSIA data structures.
Definition: DeviceInterface.hpp:33
Definition: VecWidgets.hpp:20