Vuo  2.4.0
VuoInputEditorPoint3d.cc
Go to the documentation of this file.
1
11
16{
17 return new VuoInputEditorPoint3d();
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* VuoInputEditorPoint3d::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* VuoInputEditorPoint3d::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 VuoInputEditorPoint3d::setUpDialog(QDialog &dialog, json_object *originalValue, json_object *details)
72{
73 current = VuoPoint3d_makeFromJson(originalValue);
74
75 const double max_dbl = std::numeric_limits<double>::max();
76
77 VuoPoint3d suggestedMin = VuoPoint3d_make(-max_dbl, -max_dbl, -max_dbl);
78 VuoPoint3d suggestedMax = VuoPoint3d_make( max_dbl, max_dbl, max_dbl);
79 VuoPoint3d suggestedStep = VuoPoint3d_make(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 = VuoPoint3d_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 = VuoPoint3d_makeFromJson(suggestedMaxValue);
102 else
103 hasMinMax = false;
104
105 // "suggestedStep"
106 if (hasMinMax)
107 suggestedStep = VuoPoint3d_make((suggestedMax.x - suggestedMin.x)/10.,
108 (suggestedMax.y - suggestedMin.y)/10.,
109 (suggestedMax.z - suggestedMin.z)/10.);
110 json_object *suggestedStepValue = NULL;
111 if (json_object_object_get_ex(details, "suggestedStep", &suggestedStepValue))
112 suggestedStep = VuoPoint3d_makeFromJson(suggestedStepValue);
113 }
114
115 suggestedMinForCoord[coord_x] = suggestedMin.x;
116 suggestedMinForCoord[coord_y] = suggestedMin.y;
117 suggestedMinForCoord[coord_z] = suggestedMin.z;
118
119 suggestedMaxForCoord[coord_x] = suggestedMax.x;
120 suggestedMaxForCoord[coord_y] = suggestedMax.y;
121 suggestedMaxForCoord[coord_z] = suggestedMax.z;
122
123 suggestedStepForCoord[coord_x] = suggestedStep.x;
124 suggestedStepForCoord[coord_y] = suggestedStep.y;
125 suggestedStepForCoord[coord_z] = suggestedStep.z;
126
127 spinboxForCoord[coord_x] = initSpinBox(coord_x, dialog, current.x);
128 spinboxForCoord[coord_y] = initSpinBox(coord_y, dialog, current.y);
129 spinboxForCoord[coord_z] = initSpinBox(coord_z, dialog, current.z);
130
131 connect(spinboxForCoord[coord_x], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint3d::onSpinboxUpdate);
132 connect(spinboxForCoord[coord_y], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint3d::onSpinboxUpdate);
133 connect(spinboxForCoord[coord_z], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint3d::onSpinboxUpdate);
134
135 if(hasMinMax)
136 {
137 sliderForCoord[coord_x] = initSlider(coord_x, dialog, current.x);
138 sliderForCoord[coord_y] = initSlider(coord_y, dialog, current.y);
139 sliderForCoord[coord_z] = initSlider(coord_z, dialog, current.z);
140
141 connect(sliderForCoord[coord_x], &QSlider::valueChanged, this, &VuoInputEditorPoint3d::onSliderUpdate);
142 connect(sliderForCoord[coord_y], &QSlider::valueChanged, this, &VuoInputEditorPoint3d::onSliderUpdate);
143 connect(sliderForCoord[coord_z], &QSlider::valueChanged, this, &VuoInputEditorPoint3d::onSliderUpdate);
144 }
145
146 // layout dialog
147 QGridLayout* layout = new QGridLayout;
148 dialog.setLayout(layout);
149
150 // left, top, right, bottom
151 // when showing sliders, add a little extra margin on the bottom since QSlider takes up the
152 // entire vertical spacing
153 layout->setContentsMargins(4, 4, 16, 4);
154 layout->setSpacing(4);
155
156 int row = 0;
157
158 layout->addWidget(makeLabel("X"), row, 0, Qt::AlignHCenter);
159 layout->addWidget(spinboxForCoord[coord_x], row++, 1);
160 if(hasMinMax) layout->addWidget(sliderForCoord[coord_x], row++, 1);
161
162 layout->addWidget(makeLabel("Y"), row, 0, Qt::AlignHCenter);
163 layout->addWidget(spinboxForCoord[coord_y], row++, 1);
164 if(hasMinMax) layout->addWidget(sliderForCoord[coord_y], row++, 1);
165
166 layout->addWidget(makeLabel("Z"), row, 0, Qt::AlignHCenter);
167 layout->addWidget(spinboxForCoord[coord_z], row++, 1);
168 if(hasMinMax) layout->addWidget(sliderForCoord[coord_z], row++, 1);
169
170 // forces dialog to min acceptable size
171 dialog.setMaximumWidth(1);
172 dialog.setMaximumHeight(1);
173
174 dialog.adjustSize();
175
176 // Layout details
177 setFirstWidgetInTabOrder(spinboxForCoord[coord_x]);
178 setLastWidgetInTabOrder(spinboxForCoord[coord_z]);
179
180 // Return focus to the topmost line edit by default, or to the bottommost
181 // line edit if tab-cycling backwards.
182 // To be handled properly for https://b33p.net/kosada/node/6365 .
183 (tabCycleForward ? spinboxForCoord[coord_x] : spinboxForCoord[coord_z])->setFocus();
184 (tabCycleForward ? spinboxForCoord[coord_x] : spinboxForCoord[coord_z])->selectAll();
185}
186
187bool VuoInputEditorPoint3d::getCoordFromQObject(QObject* sender, VuoInputEditorPoint3d::coord* whichCoord)
188{
189 if(sender == spinboxForCoord[coord_x] || sender == sliderForCoord[coord_x])
190 *whichCoord = coord_x;
191 else if(sender == spinboxForCoord[coord_y] || sender == sliderForCoord[coord_y])
192 *whichCoord = coord_y;
193 else if(sender == spinboxForCoord[coord_z] || sender == sliderForCoord[coord_z])
194 *whichCoord = coord_z;
195 else
196 return false;
197
198 return true;
199}
200
201void VuoInputEditorPoint3d::setCoord(coord c, double value)
202{
203 if(c == coord_x)
204 current.x = value;
205 else if(c == coord_y)
206 current.y = value;
207 else if(c == coord_z)
208 current.z = value;
209}
210
214void VuoInputEditorPoint3d::onSliderUpdate(int sliderValue)
215{
216 coord whichCoord;
217
218 if(!getCoordFromQObject(QObject::sender(), &whichCoord))
219 return;
220
221 QSlider *targetSlider = sliderForCoord[whichCoord];
222
223 double value = VuoDoubleSpinBox::sliderToDouble(targetSlider->minimum(),
224 targetSlider->maximum(),
225 suggestedMinForCoord[whichCoord],
226 suggestedMaxForCoord[whichCoord],
227 sliderValue);
228 setCoord(whichCoord, value);
229
230 // disconnect before setting spinbox value otherwise onSpinboxUpdate is called and the whole thing just cycles
231 disconnect(spinboxForCoord[whichCoord], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint3d::onSpinboxUpdate);
232 spinboxForCoord[whichCoord]->setValue( value );
233 connect(spinboxForCoord[whichCoord], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint3d::onSpinboxUpdate);
234
235 spinboxForCoord[whichCoord]->setFocus();
236 spinboxForCoord[whichCoord]->selectAll();
237
239}
240
244void VuoInputEditorPoint3d::onSpinboxUpdate(QString spinboxValue)
245{
246 coord whichCoord;
247
248 if(!getCoordFromQObject(QObject::sender(), &whichCoord))
249 return;
250
251 double value = QLocale().toDouble(spinboxValue);
252 setCoord(whichCoord, value);
253
254 QSlider *targetSlider = sliderForCoord[whichCoord];
255
256 if(targetSlider != NULL)
257 {
258 int sliderValue = VuoDoubleSpinBox::doubleToSlider(targetSlider->minimum(), targetSlider->maximum(), suggestedMinForCoord[whichCoord], suggestedMaxForCoord[whichCoord], value);
259 disconnect(targetSlider, &QSlider::valueChanged, this, &VuoInputEditorPoint3d::onSliderUpdate);
260 targetSlider->setValue( sliderValue );
261 connect(targetSlider, &QSlider::valueChanged, this, &VuoInputEditorPoint3d::onSliderUpdate);
262 }
263
264 emitValueChanged();
265}
266
271{
272 return VuoPoint3d_getJson(current);
273}
274
278void VuoInputEditorPoint3d::emitValueChanged()
279{
281}