Vuo  2.4.0
VuoInputEditorPoint4d.cc
Go to the documentation of this file.
1
11
16{
17 return new VuoInputEditorPoint4d();
18}
19
23QLabel* makeLabel(const char* text)
24{
25 QLabel* label = new QLabel(text);
26 label->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
27 return label;
28}
29
33VuoDoubleSpinBox* VuoInputEditorPoint4d::initSpinBox(coord whichCoord, QDialog& dialog, double initialValue)
34{
35 VuoDoubleSpinBox* spin = new VuoDoubleSpinBox(&dialog, 7);
36 const int decimalPrecision = DBL_MAX_10_EXP + DBL_DIG;
37 spin->setDecimals(decimalPrecision);
38 spin->setFixedWidth(100);
39 spin->setButtonMinimum(suggestedMinForCoord[whichCoord]);
40 spin->setButtonMaximum(suggestedMaxForCoord[whichCoord]);
41 spin->setSingleStep(suggestedStepForCoord[whichCoord]);
42 spin->setValue(initialValue);
43 return spin;
44}
45
49QSlider* VuoInputEditorPoint4d::initSlider(coord whichCoord, QDialog& dialog, double initialValue)
50{
51 double min = suggestedMinForCoord[whichCoord];
52 double max = suggestedMaxForCoord[whichCoord];
53 double step = suggestedStepForCoord[whichCoord];
54 double range = max - min;
55
56 QSlider* slider = new QSlider(&dialog);
57 // slider->setAttribute(Qt::WA_MacSmallSize);
58 slider->setOrientation(Qt::Horizontal);
59 slider->setFocusPolicy(Qt::NoFocus);
60 slider->setMinimum(0);
61 slider->setMaximum(slider->width());
62 slider->setSingleStep( fmax(1, step * (slider->maximum() - slider->minimum()) / range ) );
63 slider->setValue( VuoDoubleSpinBox::doubleToSlider(slider->minimum(), slider->maximum(), min, max, initialValue) );
64 return slider;
65}
66
71void VuoInputEditorPoint4d::setUpDialog(QDialog &dialog, json_object *originalValue, json_object *details)
72{
73 current = VuoPoint4d_makeFromJson(originalValue);
74
75 const double max_dbl = std::numeric_limits<double>::max();
76
77 VuoPoint4d suggestedMin = VuoPoint4d_make(-max_dbl, -max_dbl, -max_dbl, -max_dbl);
78 VuoPoint4d suggestedMax = VuoPoint4d_make( max_dbl, max_dbl, max_dbl, max_dbl);
79 VuoPoint4d suggestedStep = VuoPoint4d_make(1.0, 1.0, 1.0, 1.0);
80
81 bool hasMinMax = true;
82 bool tabCycleForward = true;
83
84 // Parse supported port annotations from the port's "details" JSON object:
85 if (details)
86 {
87 json_object *forwardTabTraversal = NULL;
88 if (json_object_object_get_ex(details, "forwardTabTraversal", &forwardTabTraversal))
89 tabCycleForward = json_object_get_boolean(forwardTabTraversal);
90
91 // "suggestedMin"
92 json_object *suggestedMinValue = NULL;
93 if (json_object_object_get_ex(details, "suggestedMin", &suggestedMinValue))
94 suggestedMin = VuoPoint4d_makeFromJson(suggestedMinValue);
95 else
96 hasMinMax = false;
97
98 // "suggestedMax"
99 json_object *suggestedMaxValue = NULL;
100 if (json_object_object_get_ex(details, "suggestedMax", &suggestedMaxValue))
101 suggestedMax = VuoPoint4d_makeFromJson(suggestedMaxValue);
102 else
103 hasMinMax = false;
104
105 // "suggestedStep"
106 if (hasMinMax)
107 suggestedStep = VuoPoint4d_make((suggestedMax.x - suggestedMin.x)/10.,
108 (suggestedMax.y - suggestedMin.y)/10.,
109 (suggestedMax.z - suggestedMin.z)/10.,
110 (suggestedMax.w - suggestedMin.w)/10.);
111 json_object *suggestedStepValue = NULL;
112 if (json_object_object_get_ex(details, "suggestedStep", &suggestedStepValue))
113 suggestedStep = VuoPoint4d_makeFromJson(suggestedStepValue);
114 }
115
116 suggestedMinForCoord[coord_x] = suggestedMin.x;
117 suggestedMinForCoord[coord_y] = suggestedMin.y;
118 suggestedMinForCoord[coord_z] = suggestedMin.z;
119 suggestedMinForCoord[coord_w] = suggestedMin.w;
120
121 suggestedMaxForCoord[coord_x] = suggestedMax.x;
122 suggestedMaxForCoord[coord_y] = suggestedMax.y;
123 suggestedMaxForCoord[coord_z] = suggestedMax.z;
124 suggestedMaxForCoord[coord_w] = suggestedMax.w;
125
126 suggestedStepForCoord[coord_x] = suggestedStep.x;
127 suggestedStepForCoord[coord_y] = suggestedStep.y;
128 suggestedStepForCoord[coord_z] = suggestedStep.z;
129 suggestedStepForCoord[coord_w] = suggestedStep.w;
130
131 spinboxForCoord[coord_x] = initSpinBox(coord_x, dialog, current.x);
132 spinboxForCoord[coord_y] = initSpinBox(coord_y, dialog, current.y);
133 spinboxForCoord[coord_z] = initSpinBox(coord_z, dialog, current.z);
134 spinboxForCoord[coord_w] = initSpinBox(coord_w, dialog, current.w);
135
136 connect(spinboxForCoord[coord_x], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint4d::onSpinboxUpdate);
137 connect(spinboxForCoord[coord_y], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint4d::onSpinboxUpdate);
138 connect(spinboxForCoord[coord_z], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint4d::onSpinboxUpdate);
139 connect(spinboxForCoord[coord_w], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint4d::onSpinboxUpdate);
140
141 if(hasMinMax)
142 {
143 sliderForCoord[coord_x] = initSlider(coord_x, dialog, current.x);
144 sliderForCoord[coord_y] = initSlider(coord_y, dialog, current.y);
145 sliderForCoord[coord_z] = initSlider(coord_z, dialog, current.z);
146 sliderForCoord[coord_w] = initSlider(coord_w, dialog, current.w);
147
148 connect(sliderForCoord[coord_x], &QSlider::valueChanged, this, &VuoInputEditorPoint4d::onSliderUpdate);
149 connect(sliderForCoord[coord_y], &QSlider::valueChanged, this, &VuoInputEditorPoint4d::onSliderUpdate);
150 connect(sliderForCoord[coord_z], &QSlider::valueChanged, this, &VuoInputEditorPoint4d::onSliderUpdate);
151 connect(sliderForCoord[coord_w], &QSlider::valueChanged, this, &VuoInputEditorPoint4d::onSliderUpdate);
152 }
153
154 // layout dialog
155 QGridLayout* layout = new QGridLayout;
156 dialog.setLayout(layout);
157
158 // left, top, right, bottom
159 // when showing sliders, add a little extra margin on the bottom since QSlider takes up the
160 // entire vertical spacing
161 layout->setContentsMargins(4, 4, 16, 4);
162 layout->setSpacing(4);
163
164 int row = 0;
165
166 layout->addWidget(makeLabel("X"), row, 0, Qt::AlignHCenter);
167 layout->addWidget(spinboxForCoord[coord_x], row++, 1);
168 if(hasMinMax) layout->addWidget(sliderForCoord[coord_x], row++, 1);
169
170 layout->addWidget(makeLabel("Y"), row, 0, Qt::AlignHCenter);
171 layout->addWidget(spinboxForCoord[coord_y], row++, 1);
172 if(hasMinMax) layout->addWidget(sliderForCoord[coord_y], row++, 1);
173
174 layout->addWidget(makeLabel("Z"), row, 0, Qt::AlignHCenter);
175 layout->addWidget(spinboxForCoord[coord_z], row++, 1);
176 if(hasMinMax) layout->addWidget(sliderForCoord[coord_z], row++, 1);
177
178 layout->addWidget(makeLabel("W"), row, 0, Qt::AlignHCenter);
179 layout->addWidget(spinboxForCoord[coord_w], row++, 1);
180 if(hasMinMax) layout->addWidget(sliderForCoord[coord_w], row++, 1);
181
182 // forces dialog to min acceptable size
183 dialog.setMaximumWidth(1);
184 dialog.setMaximumHeight(1);
185
186 dialog.adjustSize();
187
188 // Layout details
189 setFirstWidgetInTabOrder(spinboxForCoord[coord_x]);
190 setLastWidgetInTabOrder(spinboxForCoord[coord_w]);
191
192 // Return focus to the topmost line edit by default, or to the bottommost
193 // line edit if tab-cycling backwards.
194 // To be handled properly for https://b33p.net/kosada/node/6365 .
195 (tabCycleForward ? spinboxForCoord[coord_x] : spinboxForCoord[coord_w])->setFocus();
196 (tabCycleForward ? spinboxForCoord[coord_x] : spinboxForCoord[coord_w])->selectAll();
197}
198
199bool VuoInputEditorPoint4d::getCoordFromQObject(QObject* sender, VuoInputEditorPoint4d::coord* whichCoord)
200{
201 if(sender == spinboxForCoord[coord_x] || sender == sliderForCoord[coord_x])
202 *whichCoord = coord_x;
203 else if(sender == spinboxForCoord[coord_y] || sender == sliderForCoord[coord_y])
204 *whichCoord = coord_y;
205 else if(sender == spinboxForCoord[coord_z] || sender == sliderForCoord[coord_z])
206 *whichCoord = coord_z;
207 else if(sender == spinboxForCoord[coord_w] || sender == sliderForCoord[coord_w])
208 *whichCoord = coord_w;
209 else
210 return false;
211
212 return true;
213}
214
215void VuoInputEditorPoint4d::setCoord(coord c, double value)
216{
217 if(c == coord_x)
218 current.x = value;
219 else if(c == coord_y)
220 current.y = value;
221 else if(c == coord_z)
222 current.z = value;
223 else if(c == coord_w)
224 current.w = value;
225}
226
230void VuoInputEditorPoint4d::onSliderUpdate(int sliderValue)
231{
232 coord whichCoord;
233
234 if(!getCoordFromQObject(QObject::sender(), &whichCoord))
235 return;
236
237 QSlider *targetSlider = sliderForCoord[whichCoord];
238
239 double value = VuoDoubleSpinBox::sliderToDouble(targetSlider->minimum(),
240 targetSlider->maximum(),
241 suggestedMinForCoord[whichCoord],
242 suggestedMaxForCoord[whichCoord],
243 sliderValue);
244 setCoord(whichCoord, value);
245
246 // disconnect before setting spinbox value otherwise onSpinboxUpdate is called and the whole thing just cycles
247 disconnect(spinboxForCoord[whichCoord], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint4d::onSpinboxUpdate);
248 spinboxForCoord[whichCoord]->setValue( value );
249 connect(spinboxForCoord[whichCoord], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint4d::onSpinboxUpdate);
250
251 spinboxForCoord[whichCoord]->setFocus();
252 spinboxForCoord[whichCoord]->selectAll();
253
255}
256
260void VuoInputEditorPoint4d::onSpinboxUpdate(QString spinboxValue)
261{
262 coord whichCoord;
263
264 if(!getCoordFromQObject(QObject::sender(), &whichCoord))
265 return;
266
267 double value = QLocale().toDouble(spinboxValue);
268 setCoord(whichCoord, value);
269
270 QSlider *targetSlider = sliderForCoord[whichCoord];
271
272 if(targetSlider != NULL)
273 {
274 int sliderValue = VuoDoubleSpinBox::doubleToSlider(targetSlider->minimum(), targetSlider->maximum(), suggestedMinForCoord[whichCoord], suggestedMaxForCoord[whichCoord], value);
275 disconnect(targetSlider, &QSlider::valueChanged, this, &VuoInputEditorPoint4d::onSliderUpdate);
276 targetSlider->setValue( sliderValue );
277 connect(targetSlider, &QSlider::valueChanged, this, &VuoInputEditorPoint4d::onSliderUpdate);
278 }
279
280 emitValueChanged();
281}
282
287{
288 return VuoPoint4d_getJson(current);
289}
290
294void VuoInputEditorPoint4d::emitValueChanged()
295{
297}