EffectLayout.hpp
1 #pragma once
2 #include <Process/Dataflow/PortFactory.hpp>
3 #include <Process/Dataflow/PortItem.hpp>
4 
5 #include <score/graphics/RectItem.hpp>
6 #include <score/graphics/TextItem.hpp>
7 
8 #include <QPointF>
9 
10 #include <cmath>
11 
12 #include <cstdint>
13 namespace Process
14 {
15 
16 static const constexpr int MaxRowsInEffect = 5;
17 
18 // TODO not very efficient since it recomputes everything every time...
19 // Does a grid layout with maximum N rows per column.
20 template <typename F>
21 QPointF currentWidgetPos(int controlIndex, F getControlSize) noexcept(
22  noexcept(getControlSize(0)))
23 {
24  int N = MaxRowsInEffect * (controlIndex / MaxRowsInEffect);
25  qreal x = 0;
26  for(int i = 0; i < N;)
27  {
28  qreal w = 0;
29  for(int j = i; j < i + MaxRowsInEffect && j < N; j++)
30  {
31  auto sz = getControlSize(j);
32  w = std::max(w, sz.width());
33  }
34  x += w;
35  i += MaxRowsInEffect;
36  }
37 
38  qreal y = 0;
39  for(int j = N; j < controlIndex; j++)
40  {
41  auto sz = getControlSize(j);
42  y += sz.height();
43  }
44 
45  return {x, y};
46 }
47 
48 template <
49  typename CreatePort, typename CreateControl, typename GetControlSize,
50  typename GetName, typename GetFactory>
52 {
53  CreatePort createPort;
54  CreateControl createControl;
55  GetControlSize getControlSize;
56  GetName name;
57  GetFactory getFactory;
58 };
59 
60 template <typename... Args>
61 auto controlSetup(Args&&... args)
62 {
63  if constexpr(sizeof...(Args) == 4)
64  {
65  return controlSetup(
66  std::forward<Args>(args)...,
67  [](const Process::PortFactoryList& portFactory, Process::Port& port)
68  -> Process::PortFactory& { return *portFactory.get(port.concreteKey()); });
69  }
70  else
71  {
72  return ControlSetup<Args...>{std::forward<Args>(args)...};
73  }
74 }
75 
76 template <typename T>
77 [[deprecated]] auto createControl(
78  int i,
79  const auto& setup, // See ControlSetup
80  T& port, const Process::PortFactoryList& portFactory, const Process::Context& doc,
81  QGraphicsItem* parentItem, QObject* parent)
82 {
83  // TODO put the port at the correct order wrt its index ?
84  auto item = new score::EmptyRectItem{parentItem};
85 
86  // Create the port
87  auto& fact = setup.getFactory(portFactory, port);
88  auto portItem = setup.createPort(fact, port, doc, item, parent);
89 
90  // Create the label
91  auto lab = Dataflow::makePortLabel(port, item);
92 
93  // Create the control
94  struct Controls
95  {
96  score::EmptyRectItem* item{};
97  Dataflow::PortItem* port{};
98  QGraphicsItem* widg{};
99  score::SimpleTextItem* label{};
100  QRectF itemRect;
101  };
102 
103  if(QGraphicsItem* widg = setup.createControl(fact, port, doc, item, parent))
104  {
105  widg->setParentItem(item);
106 
107  // Layout the items
108  const qreal labelHeight = 10;
109  const qreal labelWidth = lab->boundingRect().width();
110  const auto wrect = widg->boundingRect();
111  const qreal widgetHeight = wrect.height();
112  const qreal widgetWidth = wrect.width();
113 
114  auto h = std::max(20., (qreal)(widgetHeight + labelHeight + 7.));
115  auto w = std::max(90., std::max(25. + labelWidth, widgetWidth));
116 
117  portItem->setPos(8., 4.);
118  lab->setPos(20., 2);
119  widg->setPos(18., labelHeight + 5.);
120 
121  const auto itemRect = QRectF{0., 0, w, h};
122 
123  QPointF pos = Process::currentWidgetPos(i, setup.getControlSize);
124  item->setPos(pos);
125  item->setRect(itemRect);
126  item->setToolTip(QString("%1\n%2").arg(port.name(), port.description()));
127 
128  return Controls{item, portItem, widg, lab, itemRect};
129  }
130  else
131  {
132  QRectF itemRect{0., 0, 90., 30.};
133  QPointF pos = Process::currentWidgetPos(i, setup.getControlSize);
134  portItem->setPos(8., 4.);
135  lab->setPos(20., 2);
136  item->setPos(pos);
137  item->setRect(itemRect);
138  item->setToolTip(QString("%1\n%2").arg(port.name(), port.description()));
139 
140  return Controls{item, portItem, nullptr, lab, itemRect};
141  }
142 }
143 
144 template <typename C, typename T>
145 [[deprecated]] static auto makeControl(
146  C& ctrl, T& inlet, QGraphicsItem& parent, QObject& context,
147  const Process::Context& doc, const Process::PortFactoryList& portFactory)
148 {
149  auto item = new score::EmptyItem{&parent};
150 
151  // Port
152  Process::PortFactory* fact = portFactory.get(inlet.concreteKey());
153  auto port = fact->makePortItem(inlet, doc, item, &context);
154  port->setPos(0, 1.);
155 
156  // Text
157  auto lab = Dataflow::makePortLabel(inlet, item);
158  lab->setPos(12, 0);
159 
160  // Control
161  auto widg = ctrl.make_item(ctrl, inlet, doc, nullptr, &context);
162  widg->setParentItem(item);
163  widg->setPos(0, 12.);
164 
165  // Create a single control
166  struct ControlItem
167  {
168  QGraphicsItem& root;
169  Dataflow::PortItem& port;
170  score::SimpleTextItem& text;
171  decltype(*widg)& control;
172  };
173  return ControlItem{*item, *port, *lab, *widg};
174 }
175 
176 template <typename C, typename T>
177 [[deprecated]] static auto makeControlNoText(
178  C& ctrl, T& inlet, QGraphicsItem& parent, QObject& context,
179  const Process::Context& doc, const Process::PortFactoryList& portFactory)
180 {
181  auto item = new score::EmptyItem{&parent};
182 
183  // Control
184  auto widg = ctrl.make_item(ctrl, inlet, doc, nullptr, &context);
185  widg->setParentItem(item);
186 
187  // Port
188  Process::PortFactory* fact = portFactory.get(inlet.concreteKey());
189  auto port = fact->makePortItem(inlet, doc, item, &context);
190 
191  // Create a single control
192  struct ControlItem
193  {
194  score::EmptyItem& root;
195  Dataflow::PortItem& port;
196  decltype(*widg)& control;
197  };
198  return ControlItem{*item, *port, *widg};
199 }
200 }
Definition: score-lib-process/Process/Dataflow/PortItem.hpp:39
Definition: PortFactory.hpp:30
Definition: PortFactory.hpp:74
Definition: Port.hpp:102
Definition: RectItem.hpp:123
Definition: RectItem.hpp:64
FactoryType * get(const key_type &k) const noexcept
Get a particular factory from its ConcreteKey.
Definition: InterfaceList.hpp:123
Definition: TextItem.hpp:28
Base classes and tools to implement processes and layers.
Definition: JSONVisitor.hpp:1324
Definition: ProcessContext.hpp:12
Definition: EffectLayout.hpp:52