Vuo  2.4.0
VuoInputEditorPoint2d.cc
Go to the documentation of this file.
1
11
16{
17 return new VuoInputEditorPoint2d();
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* VuoInputEditorPoint2d::initSpinBox(coord whichCoord, QDialog& dialog, double initialValue)
34{
35 VuoDoubleSpinBox* spin = new VuoDoubleSpinBox(&dialog, 7);
36 const int decimalPrecision = FLT_MAX_10_EXP + FLT_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* VuoInputEditorPoint2d::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->setOrientation(Qt::Horizontal);
58 slider->setFocusPolicy(Qt::NoFocus);
59 slider->setMinimum(0);
60 slider->setMaximum(slider->width());
61 slider->setSingleStep( fmax(1, step * (slider->maximum() - slider->minimum()) / range ) );
62 slider->setValue( VuoDoubleSpinBox::doubleToSlider(slider->minimum(), slider->maximum(), min, max, initialValue) );
63 return slider;
64}
65
70void VuoInputEditorPoint2d::setUpDialog(QDialog &dialog, json_object *originalValue, json_object *details)
71{
72 current = VuoPoint2d_makeFromJson(originalValue);
73
74 const double max_dbl = std::numeric_limits<double>::max();
75
76 VuoPoint2d suggestedMin = VuoPoint2d_make(-max_dbl, -max_dbl);
77 VuoPoint2d suggestedMax = VuoPoint2d_make( max_dbl, max_dbl);
78 VuoPoint2d suggestedStep = VuoPoint2d_make(1.0, 1.0);
79
80 bool hasMinMax = true;
81 bool tabCycleForward = true;
82
83 // Parse supported port annotations from the port's "details" JSON object:
84 if (details)
85 {
86 json_object *forwardTabTraversal = NULL;
87 if (json_object_object_get_ex(details, "forwardTabTraversal", &forwardTabTraversal))
88 tabCycleForward = json_object_get_boolean(forwardTabTraversal);
89
90 // "suggestedMin"
91 json_object *suggestedMinValue = NULL;
92 if (json_object_object_get_ex(details, "suggestedMin", &suggestedMinValue))
93 suggestedMin = VuoPoint2d_makeFromJson(suggestedMinValue);
94 else
95 hasMinMax = false;
96
97 // "suggestedMax"
98 json_object *suggestedMaxValue = NULL;
99 if (json_object_object_get_ex(details, "suggestedMax", &suggestedMaxValue))
100 suggestedMax = VuoPoint2d_makeFromJson(suggestedMaxValue);
101 else
102 hasMinMax = false;
103
104 // "suggestedStep"
105 if (hasMinMax)
106 suggestedStep = VuoPoint2d_make((suggestedMax.x - suggestedMin.x)/10.,
107 (suggestedMax.y - suggestedMin.y)/10.);
108 json_object *suggestedStepValue = NULL;
109 if (json_object_object_get_ex(details, "suggestedStep", &suggestedStepValue))
110 suggestedStep = VuoPoint2d_makeFromJson(suggestedStepValue);
111 }
112
113 suggestedMinForCoord[coord_x] = suggestedMin.x;
114 suggestedMinForCoord[coord_y] = suggestedMin.y;
115 suggestedMaxForCoord[coord_x] = suggestedMax.x;
116 suggestedMaxForCoord[coord_y] = suggestedMax.y;
117 suggestedStepForCoord[coord_x] = suggestedStep.x;
118 suggestedStepForCoord[coord_y] = suggestedStep.y;
119
120 spinboxForCoord[coord_x] = initSpinBox(coord_x, dialog, current.x);
121 spinboxForCoord[coord_y] = initSpinBox(coord_y, dialog, current.y);
122 connect(spinboxForCoord[coord_x], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint2d::onSpinboxUpdate);
123 connect(spinboxForCoord[coord_y], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint2d::onSpinboxUpdate);
124
125 if(hasMinMax)
126 {
127 sliderForCoord[coord_x] = initSlider(coord_x, dialog, current.x);
128 sliderForCoord[coord_y] = initSlider(coord_y, dialog, current.y);
129 connect(sliderForCoord[coord_x], &QSlider::valueChanged, this, &VuoInputEditorPoint2d::onSliderUpdate);
130 connect(sliderForCoord[coord_y], &QSlider::valueChanged, this, &VuoInputEditorPoint2d::onSliderUpdate);
131 }
132
133 // layout dialog
134 QGridLayout* layout = new QGridLayout;
135 dialog.setLayout(layout);
136
137 // left, top, right, bottom
138 // when showing sliders, add a little extra margin on the bottom since QSlider takes up the
139 // entire vertical spacing
140 layout->setContentsMargins(4, 4, 16, 4);
141 layout->setSpacing(4);
142
143 int row = 0;
144
145 layout->addWidget(makeLabel("X"), row, 0, Qt::AlignHCenter);
146 layout->addWidget(spinboxForCoord[coord_x], row++, 1);
147 if(hasMinMax) layout->addWidget(sliderForCoord[coord_x], row++, 1);
148
149 layout->addWidget(makeLabel("Y"), row, 0, Qt::AlignHCenter);
150 layout->addWidget(spinboxForCoord[coord_y], row++, 1);
151 if(hasMinMax) layout->addWidget(sliderForCoord[coord_y], row++, 1);
152
153 dialog.setMaximumWidth(1);
154 dialog.setMaximumHeight(1);
155
156 dialog.adjustSize();
157
158 // Layout details
159 setFirstWidgetInTabOrder(spinboxForCoord[coord_x]);
160 setLastWidgetInTabOrder(spinboxForCoord[coord_y]);
161
162 // Return focus to the topmost line edit by default, or to the bottommost
163 // line edit if tab-cycling backwards.
164 // To be handled properly for https://b33p.net/kosada/node/6365 .
165 (tabCycleForward ? spinboxForCoord[coord_x] : spinboxForCoord[coord_y])->setFocus();
166 (tabCycleForward ? spinboxForCoord[coord_x] : spinboxForCoord[coord_y])->selectAll();
167}
168
169bool VuoInputEditorPoint2d::getCoordFromQObject(QObject* sender, VuoInputEditorPoint2d::coord* whichCoord)
170{
171 if(sender == spinboxForCoord[coord_x] || sender == sliderForCoord[coord_x])
172 *whichCoord = coord_x;
173 else if(sender == spinboxForCoord[coord_y] || sender == sliderForCoord[coord_y])
174 *whichCoord = coord_y;
175 else
176 return false;
177
178 return true;
179}
180
181void VuoInputEditorPoint2d::setCoord(coord c, double value)
182{
183 if(c == coord_x)
184 current.x = value;
185 else if(c == coord_y)
186 current.y = value;
187}
188
192void VuoInputEditorPoint2d::onSliderUpdate(int sliderValue)
193{
194 coord whichCoord;
195
196 if(!getCoordFromQObject(QObject::sender(), &whichCoord))
197 return;
198
199 QSlider *targetSlider = sliderForCoord[whichCoord];
200
201 double value = VuoDoubleSpinBox::sliderToDouble(targetSlider->minimum(),
202 targetSlider->maximum(),
203 suggestedMinForCoord[whichCoord],
204 suggestedMaxForCoord[whichCoord],
205 sliderValue);
206 setCoord(whichCoord, value);
207
208 // disconnect before setting spinbox value otherwise onSpinboxUpdate is called and the whole thing just cycles
209 disconnect(spinboxForCoord[whichCoord], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint2d::onSpinboxUpdate);
210 spinboxForCoord[whichCoord]->setValue( value );
211 connect(spinboxForCoord[whichCoord], static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged), this, &VuoInputEditorPoint2d::onSpinboxUpdate);
212
213 spinboxForCoord[whichCoord]->setFocus();
214 spinboxForCoord[whichCoord]->selectAll();
215
217}
218
222void VuoInputEditorPoint2d::onSpinboxUpdate(QString spinboxValue)
223{
224 coord whichCoord;
225
226 if(!getCoordFromQObject(QObject::sender(), &whichCoord))
227 return;
228
229 double value = QLocale().toDouble(spinboxValue);
230 setCoord(whichCoord, value);
231
232 QSlider *targetSlider = sliderForCoord[whichCoord];
233
234 if(targetSlider != NULL)
235 {
236 int sliderValue = VuoDoubleSpinBox::doubleToSlider(targetSlider->minimum(), targetSlider->maximum(), suggestedMinForCoord[whichCoord], suggestedMaxForCoord[whichCoord], value);
237 disconnect(targetSlider, &QSlider::valueChanged, this, &VuoInputEditorPoint2d::onSliderUpdate);
238 targetSlider->setValue( sliderValue );
239 connect(targetSlider, &QSlider::valueChanged, this, &VuoInputEditorPoint2d::onSliderUpdate);
240 }
241
242 emitValueChanged();
243}
244
249{
250 return VuoPoint2d_getJson(current);
251}
252
256void VuoInputEditorPoint2d::emitValueChanged()
257{
259}