1
2
3 #include "toonzqt/doublepairfield.h"
4 #include "toonzqt/dvdialog.h"
5
6 #include "tcommon.h"
7
8 #include <cmath>
9
10 #include <QLabel>
11 #include <QPainter>
12 #include <QMouseEvent>
13 #include <QSlider>
14 #include <QHBoxLayout>
15
16 using namespace DVGui;
17
18 #ifdef MACOSX
19 #define MARGIN_OFFSET 7
20 #else
21 #define MARGIN_OFFSET 2
22 #endif
23
24 //=============================================================================
25 // DoubleValuePairField
26 //-----------------------------------------------------------------------------
27
DoubleValuePairField(QWidget * parent,bool isMaxRangeLimited,DoubleValueLineEdit * leftLineEdit,DoubleValueLineEdit * rightLineEdit)28 DoubleValuePairField::DoubleValuePairField(QWidget *parent,
29 bool isMaxRangeLimited,
30 DoubleValueLineEdit *leftLineEdit,
31 DoubleValueLineEdit *rightLineEdit)
32 : QWidget(parent)
33 , m_values(0, 0)
34 , m_minValue(0)
35 , m_maxValue(100)
36 , m_grabOffset(0)
37 , m_grabIndex(-1)
38 , m_leftMargin(72)
39 , m_rightMargin(72)
40 , m_isMaxRangeLimited(isMaxRangeLimited)
41 , m_leftLineEdit(leftLineEdit)
42 , m_rightLineEdit(rightLineEdit)
43 , m_isLinear(true) {
44 assert(m_leftLineEdit);
45 assert(m_rightLineEdit);
46 setObjectName("DoublePairField");
47 setFixedHeight(WidgetHeight);
48
49 m_leftLabel = new QLabel("", this);
50 m_rightLabel = new QLabel("", this);
51
52 m_leftLineEdit->setFixedWidth(60);
53 m_rightLineEdit->setFixedWidth(60);
54
55 //---- layout
56 QHBoxLayout *m_mainLayout = new QHBoxLayout;
57 m_mainLayout->setMargin(0);
58 m_mainLayout->setSpacing(3);
59 {
60 m_mainLayout->addWidget(m_leftLabel, 1);
61 m_mainLayout->addWidget(m_leftLineEdit, 1, Qt::AlignLeft);
62 m_mainLayout->addSpacing(35);
63 m_mainLayout->addStretch(100);
64 m_mainLayout->addWidget(m_rightLabel, 1);
65 m_mainLayout->addWidget(m_rightLineEdit, 1, Qt::AlignRight);
66 }
67 setLayout(m_mainLayout);
68
69 //---- signal-slot connections
70 bool ret = connect(m_leftLineEdit, SIGNAL(editingFinished()),
71 SLOT(onLeftEditingFinished()));
72 ret = ret && connect(m_rightLineEdit, SIGNAL(editingFinished()),
73 SLOT(onRightEditingFinished()));
74 assert(ret);
75 }
76
77 //-----------------------------------------------------------------------------
78
pos2value(int x) const79 double DoubleValuePairField::pos2value(int x) const {
80 int xMin = m_leftMargin, xMax = width() - m_rightMargin - 1;
81 if (m_isLinear)
82 return m_minValue + (m_maxValue - m_minValue) * (x - xMin) / (xMax - xMin);
83
84 // nonlinear slider case
85 double posRatio = (double)(x - xMin) / (double)(xMax - xMin);
86 double t;
87 if (posRatio <= 0.5)
88 t = 0.04 * posRatio;
89 else if (posRatio <= 0.75)
90 t = -0.02 + 0.08 * posRatio;
91 else if (posRatio <= 0.9)
92 t = -0.26 + 0.4 * posRatio;
93 else
94 t = -8.0 + 9.0 * posRatio;
95 return m_minValue + (m_maxValue - m_minValue) * t;
96 }
97
98 //-----------------------------------------------------------------------------
99
value2pos(double v) const100 int DoubleValuePairField::value2pos(double v) const {
101 int xMin = m_leftMargin, xMax = width() - m_rightMargin - 1;
102 if (m_isLinear)
103 return xMin + (int)(((xMax - xMin) * (v - m_minValue)) /
104 (m_maxValue - m_minValue));
105
106 // nonlinear slider case
107 double valueRatio =
108 (v - (double)m_minValue) / (double)(m_maxValue - m_minValue);
109 double t;
110 if (valueRatio <= 0.02)
111 t = valueRatio / 0.04;
112 else if (valueRatio <= 0.04)
113 t = (valueRatio + 0.02) / 0.08;
114 else if (valueRatio <= 0.1)
115 t = (valueRatio + 0.26) / 0.4;
116 else
117 t = (valueRatio + 8.0) / 9.0;
118 return xMin + (int)(t * (double)(xMax - xMin));
119 }
120
121 //-----------------------------------------------------------------------------
122
paintEvent(QPaintEvent *)123 void DoubleValuePairField::paintEvent(QPaintEvent *) {
124 QPainter p(this);
125 p.setBrush(Qt::NoBrush);
126
127 int x0 = value2pos(m_minValue);
128 int x1 = value2pos(m_maxValue);
129 int y = height() / 2;
130
131 p.setPen(QPen(getDarkLineColor(), 4));
132 p.drawLine(x0 - 1, y, x1, y);
133
134 p.setPen(Qt::black);
135
136 int y1 = height() - 1;
137 int x;
138 x = value2pos(m_values.first);
139 QRect sliderRect = QRect(x0, -5, x1 - x0 + 1, 10);
140
141 if (sliderRect.contains(QPoint(x, 0)))
142 p.drawPixmap(x - m_handleLeftPixmap.width() + 1, 2, m_handleLeftPixmap);
143 else
144 p.drawPixmap(sliderRect.right() - m_handleLeftPixmap.width() + 1, 2,
145 m_handleLeftGrayPixmap);
146
147 x = value2pos(m_values.second);
148
149 if (sliderRect.contains(QPoint(x, 0)))
150 p.drawPixmap(x, 2, m_handleRightPixmap);
151 else
152 p.drawPixmap(sliderRect.right(), 2, m_handleRightGrayPixmap);
153 }
154
155 //-----------------------------------------------------------------------------
156
setLeftText(const QString & text)157 void DoubleValuePairField::setLeftText(const QString &text) {
158 QString oldText = m_leftLabel->text();
159
160 int oldLabelSize = fontMetrics().width(oldText);
161 int newLabelSize = fontMetrics().width(text);
162 int labelSize = newLabelSize - oldLabelSize;
163 m_leftMargin += labelSize + MARGIN_OFFSET;
164
165 m_leftLabel->setText(text);
166 update();
167 }
168
169 //-----------------------------------------------------------------------------
170
setRightText(const QString & text)171 void DoubleValuePairField::setRightText(const QString &text) {
172 QString oldText = m_rightLabel->text();
173
174 int oldLabelSize = fontMetrics().width(oldText);
175 int newLabelSize = fontMetrics().width(text);
176 int labelSize = newLabelSize - oldLabelSize;
177 m_rightMargin += labelSize + MARGIN_OFFSET;
178
179 m_rightLabel->setText(text);
180 update();
181 }
182
183 //-----------------------------------------------------------------------------
184
setLabelsEnabled(bool enable)185 void DoubleValuePairField::setLabelsEnabled(bool enable) {
186 if (!enable) {
187 m_rightLabel->hide();
188 m_leftLabel->hide();
189 } else {
190 m_rightLabel->show();
191 m_leftLabel->show();
192 }
193 }
194
195 //-----------------------------------------------------------------------------
196
setValue(double value)197 void DoubleValuePairField::setValue(double value) {
198 int decimals = std::min(m_leftLineEdit->getDecimals(), 4);
199 value = tround(value * std::pow(10, decimals)) * std::pow(0.1, decimals);
200 value = tcrop(value, m_minValue, m_maxValue);
201 if (m_grabIndex == 0) // Left grab
202 {
203 m_values.first = value;
204 m_leftLineEdit->setValue(m_values.first);
205
206 if (value > m_values.second) {
207 m_values.second = value;
208 m_rightLineEdit->setValue(m_values.second);
209 }
210 } else // Right grab
211 {
212 m_values.second = value;
213 m_rightLineEdit->setValue(m_values.second);
214
215 if (value < m_values.first) {
216 m_values.first = value;
217 m_leftLineEdit->setValue(m_values.first);
218 }
219 }
220 }
221
222 //-----------------------------------------------------------------------------
223
setValues(const std::pair<double,double> & values)224 void DoubleValuePairField::setValues(const std::pair<double, double> &values) {
225 assert(values.first <= values.second);
226 m_values.first = tcrop(values.first, m_minValue, m_maxValue);
227 m_leftLineEdit->setValue(m_values.first);
228
229 m_values.second = values.second;
230 if (m_isMaxRangeLimited)
231 m_values.second = tcrop(values.second, m_values.first, m_maxValue);
232 m_rightLineEdit->setValue(m_values.second);
233
234 update();
235 }
236
237 //-----------------------------------------------------------------------------
238
setRange(double minValue,double maxValue)239 void DoubleValuePairField::setRange(double minValue, double maxValue) {
240 m_minValue = minValue;
241 m_maxValue = maxValue;
242
243 if (!m_isMaxRangeLimited) maxValue = (std::numeric_limits<int>::max)();
244
245 m_leftLineEdit->setRange(minValue, maxValue);
246 m_rightLineEdit->setRange(minValue, maxValue);
247 update();
248 }
249
250 //-----------------------------------------------------------------------------
251
getRange(double & minValue,double & maxValue)252 void DoubleValuePairField::getRange(double &minValue, double &maxValue) {
253 minValue = m_minValue;
254 maxValue = m_maxValue;
255 }
256
257 //-----------------------------------------------------------------------------
258
mousePressEvent(QMouseEvent * event)259 void DoubleValuePairField::mousePressEvent(QMouseEvent *event) {
260 if (event->button() == Qt::LeftButton) {
261 int x = event->pos().x();
262 int cur0, cur1;
263 if (m_values.first > m_maxValue)
264 cur0 = value2pos(m_maxValue) - 5;
265 else
266 cur0 = value2pos(m_values.first);
267 if (m_values.second > m_maxValue)
268 cur1 = value2pos(m_maxValue);
269 else
270 cur1 = value2pos(m_values.second);
271 int d0 = abs(cur0 - x);
272 int d1 = abs(cur1 - x);
273 int d, cur;
274 if (d0 < d1 || (d0 == d1 && x < cur0)) {
275 d = abs(d0);
276 cur = cur0;
277 m_grabIndex = 0;
278 } else {
279 d = abs(d1);
280 cur = cur1;
281 m_grabIndex = 1;
282 }
283 if (d < 6)
284 m_grabOffset = cur - x;
285 else {
286 m_grabOffset = 0;
287 setValue(pos2value(x));
288 emit valuesChanged(true);
289 update();
290 }
291 }
292 }
293
294 //-----------------------------------------------------------------------------
295
mouseMoveEvent(QMouseEvent * event)296 void DoubleValuePairField::mouseMoveEvent(QMouseEvent *event) {
297 if (event->buttons()) {
298 std::pair<double, double> oldValues = m_values;
299 int x = event->pos().x() + m_grabOffset;
300 setValue(pos2value(x));
301 if (oldValues != m_values) {
302 emit valuesChanged(true);
303 update();
304 }
305 }
306 }
307
308 //-----------------------------------------------------------------------------
309
mouseReleaseEvent(QMouseEvent * event)310 void DoubleValuePairField::mouseReleaseEvent(QMouseEvent *event) {
311 m_grabOffset = 0;
312 m_grabIndex = 0;
313 emit valuesChanged(false);
314 }
315
316 //-----------------------------------------------------------------------------
317
onLeftEditingFinished()318 void DoubleValuePairField::onLeftEditingFinished() {
319 double value = m_leftLineEdit->getValue();
320 if (value == m_values.first) return;
321 if (!m_isMaxRangeLimited && value < m_minValue)
322 value = m_minValue;
323 else if (m_isMaxRangeLimited)
324 value = tcrop(value, m_minValue, m_maxValue);
325 m_values.first = value;
326 if (m_values.first > m_values.second) {
327 m_values.second = m_values.first;
328 m_rightLineEdit->setValue(m_values.second);
329 }
330 emit valuesChanged(false);
331 update();
332 }
333
334 //-----------------------------------------------------------------------------
335
onRightEditingFinished()336 void DoubleValuePairField::onRightEditingFinished() {
337 double value = m_rightLineEdit->getValue();
338 if (value == m_values.second) return;
339 if (m_isMaxRangeLimited) value = tcrop(value, m_minValue, m_maxValue);
340 m_values.second = value;
341 if (m_values.second < m_values.first) {
342 m_values.first = m_values.second;
343 m_leftLineEdit->setValue(m_values.first);
344 }
345 emit valuesChanged(false);
346 update();
347 }
348
349 //=============================================================================
350 // DoublePairField
351 //-----------------------------------------------------------------------------
352
DoublePairField(QWidget * parent,bool isMaxRangeLimited)353 DoublePairField::DoublePairField(QWidget *parent, bool isMaxRangeLimited)
354 : DoubleValuePairField(parent, isMaxRangeLimited, new DoubleLineEdit(0),
355 new DoubleLineEdit(0)) {
356 DoubleLineEdit *leftLineEdit = dynamic_cast<DoubleLineEdit *>(m_leftLineEdit);
357 leftLineEdit->setDecimals(2);
358 DoubleLineEdit *rightLineEdit =
359 dynamic_cast<DoubleLineEdit *>(m_rightLineEdit);
360 rightLineEdit->setDecimals(2);
361 }
362
363 //=============================================================================
364 // MeasuredDoublePairField
365 //-----------------------------------------------------------------------------
366
MeasuredDoublePairField(QWidget * parent,bool isMaxRangeLimited)367 MeasuredDoublePairField::MeasuredDoublePairField(QWidget *parent,
368 bool isMaxRangeLimited)
369 : DoubleValuePairField(parent, isMaxRangeLimited,
370 new MeasuredDoubleLineEdit(0),
371 new MeasuredDoubleLineEdit(0)) {
372 m_leftLineEdit->setFixedSize(63, WidgetHeight);
373 m_rightLineEdit->setFixedSize(63, WidgetHeight);
374 }
375
376 //-----------------------------------------------------------------------------
377
setMeasure(std::string measureName)378 void MeasuredDoublePairField::setMeasure(std::string measureName) {
379 MeasuredDoubleLineEdit *leftLineEdit =
380 dynamic_cast<MeasuredDoubleLineEdit *>(m_leftLineEdit);
381 assert(leftLineEdit);
382 leftLineEdit->setMeasure(measureName);
383 MeasuredDoubleLineEdit *rightLineEdit =
384 dynamic_cast<MeasuredDoubleLineEdit *>(m_rightLineEdit);
385 assert(rightLineEdit);
386 rightLineEdit->setMeasure(measureName);
387 }
388
389 //-----------------------------------------------------------------------------
390 /*--設定ファイルからインタフェースの精度を変える--*/
setPrecision(int precision)391 void MeasuredDoublePairField::setPrecision(int precision) {
392 MeasuredDoubleLineEdit *leftLineEdit =
393 dynamic_cast<MeasuredDoubleLineEdit *>(m_leftLineEdit);
394 if (leftLineEdit) leftLineEdit->setDecimals(precision);
395 MeasuredDoubleLineEdit *rightLineEdit =
396 dynamic_cast<MeasuredDoubleLineEdit *>(m_rightLineEdit);
397 if (rightLineEdit) rightLineEdit->setDecimals(precision);
398 }
399