| |
| |
| #include "toonzqt/intpairfield.h" |
| |
| #include "toonzqt/dvdialog.h" |
| |
| #include "tcommon.h" |
| |
| #include <QLabel> |
| #include <QPainter> |
| #include <QMouseEvent> |
| #include <QSlider> |
| #include <QHBoxLayout> |
| |
| using namespace DVGui; |
| |
| #ifdef MACOSX |
| #define MARGIN_OFFSET 7 |
| #else |
| #define MARGIN_OFFSET 2 |
| #endif |
| |
| |
| |
| |
| |
| IntPairField::IntPairField(QWidget *parent, bool isMaxRangeLimited) |
| : QWidget(parent), m_values(0, 0), m_minValue(0), m_maxValue(100), m_grabOffset(0), m_grabIndex(-1), m_leftMargin(52), m_rightMargin(52), m_isMaxRangeLimited(isMaxRangeLimited) |
| { |
| setObjectName("IntPairField"); |
| setFixedHeight(WidgetHeight); |
| |
| m_leftLabel = new QLabel("", this); |
| m_leftLineEdit = new IntLineEdit(this); |
| |
| m_rightLabel = new QLabel("", this); |
| m_rightLineEdit = new IntLineEdit(this); |
| |
| m_leftLineEdit->setFixedWidth(40); |
| m_rightLineEdit->setFixedWidth(40); |
| |
| |
| QHBoxLayout *m_mainLayout = new QHBoxLayout; |
| m_mainLayout->setMargin(0); |
| m_mainLayout->setSpacing(5); |
| { |
| m_mainLayout->addWidget(m_leftLabel, 1); |
| m_mainLayout->addWidget(m_leftLineEdit, 1, Qt::AlignLeft); |
| m_mainLayout->addSpacing(35); |
| m_mainLayout->addStretch(100); |
| m_mainLayout->addWidget(m_rightLabel, 1); |
| m_mainLayout->addWidget(m_rightLineEdit, 1, Qt::AlignRight); |
| } |
| setLayout(m_mainLayout); |
| |
| |
| bool ret = connect(m_leftLineEdit, SIGNAL(editingFinished()), SLOT(onLeftEditingFinished())); |
| ret = ret && connect(m_rightLineEdit, SIGNAL(editingFinished()), SLOT(onRightEditingFinished())); |
| |
| assert(ret); |
| } |
| |
| |
| |
| double IntPairField::pos2value(int x) const |
| { |
| int xMin = m_leftMargin, xMax = width() - m_rightMargin - 1; |
| return m_minValue + (m_maxValue - m_minValue) * (x - xMin) / (xMax - xMin); |
| } |
| |
| |
| |
| int IntPairField::value2pos(double v) const |
| { |
| int xMin = m_leftMargin, xMax = width() - m_rightMargin - 1; |
| return xMin + (int)(((xMax - xMin) * (v - m_minValue)) / (m_maxValue - m_minValue)); |
| } |
| |
| |
| |
| void IntPairField::paintEvent(QPaintEvent *) |
| { |
| QPainter p(this); |
| p.setBrush(Qt::NoBrush); |
| |
| int x0 = value2pos(m_minValue); |
| int x1 = value2pos(m_maxValue); |
| int y = height() / 2; |
| |
| p.setPen(getLightLineColor()); |
| p.drawLine(x0 - 1, y, x1 + 1, y); |
| p.drawPoint(x1 + 1, y - 1); |
| p.drawPoint(x1 + 1, y - 2); |
| p.drawPoint(x1 + 1, y - 3); |
| p.setPen(QColor(0, 0, 0)); |
| p.drawLine(x0, y - 2, x1 - 1, y - 2); |
| p.setPen(getDarkLineColor()); |
| p.drawLine(x0 - 1, y - 3, x1, y - 3); |
| p.drawPoint(x0 - 1, y - 1); |
| p.drawPoint(x0 - 1, y - 2); |
| |
| p.setPen(Qt::black); |
| |
| int y1 = height() - 1; |
| int x; |
| x = value2pos(m_values.first); |
| QRect sliderRect = QRect(x0, -5, x1 - x0 + 1, 10); |
| |
| if (sliderRect.contains(QPoint(x, 0))) |
| p.drawPixmap(x - m_handleLeftPixmap.width() + 1, 2, m_handleLeftPixmap); |
| else |
| p.drawPixmap(sliderRect.right() - m_handleLeftPixmap.width() + 1, 2, m_handleLeftGrayPixmap); |
| |
| x = value2pos(m_values.second); |
| |
| if (sliderRect.contains(QPoint(x, 0))) |
| p.drawPixmap(x, 2, m_handleRightPixmap); |
| else |
| p.drawPixmap(sliderRect.right(), 2, m_handleRightGrayPixmap); |
| } |
| |
| |
| |
| void IntPairField::setLeftText(const QString &text) |
| { |
| QPoint pos = m_leftLabel->pos(); |
| QString oldText = m_leftLabel->text(); |
| int oldLabelSize = fontMetrics().width(oldText); |
| int newLabelSize = fontMetrics().width(text); |
| int labelSize = newLabelSize - oldLabelSize; |
| m_leftMargin += labelSize + MARGIN_OFFSET; |
| m_leftLabel->setText(text); |
| update(); |
| } |
| |
| |
| |
| void IntPairField::setRightText(const QString &text) |
| { |
| QString oldText = m_rightLabel->text(); |
| int oldLabelSize = fontMetrics().width(oldText); |
| int newLabelSize = fontMetrics().width(text); |
| int labelSize = newLabelSize - oldLabelSize; |
| m_rightMargin += labelSize + MARGIN_OFFSET; |
| m_rightLabel->setText(text); |
| update(); |
| } |
| |
| |
| |
| void IntPairField::setLabelsEnabled(bool enable) |
| { |
| if (!enable) { |
| m_rightLabel->hide(); |
| m_leftLabel->hide(); |
| } else { |
| m_rightLabel->show(); |
| m_leftLabel->show(); |
| } |
| } |
| |
| |
| |
| void IntPairField::setValue(int value) |
| { |
| |
| value = tcrop(value, m_minValue, m_maxValue); |
| value = tround(value * 100) * 0.01; |
| if (m_grabIndex == 0) |
| { |
| m_values.first = value; |
| m_leftLineEdit->setValue(m_values.first); |
| |
| if (value > m_values.second) { |
| m_values.second = value; |
| m_rightLineEdit->setValue(m_values.second); |
| } |
| } else |
| { |
| m_values.second = value; |
| m_rightLineEdit->setValue(m_values.second); |
| |
| if (value < m_values.first) { |
| m_values.first = value; |
| m_leftLineEdit->setValue(m_values.first); |
| } |
| } |
| } |
| |
| |
| |
| void IntPairField::setValues(const std::pair<int, int> &values) |
| { |
| assert(values.first <= values.second); |
| m_values.first = tcrop(values.first, m_minValue, m_maxValue); |
| m_leftLineEdit->setValue(m_values.first); |
| |
| m_values.second = values.second; |
| if (m_isMaxRangeLimited) |
| m_values.second = tcrop(values.second, m_values.first, m_maxValue); |
| m_rightLineEdit->setValue(m_values.second); |
| |
| update(); |
| } |
| |
| |
| |
| void IntPairField::setRange(int minValue, int maxValue) |
| { |
| m_minValue = minValue; |
| m_maxValue = maxValue; |
| |
| if (!m_isMaxRangeLimited) |
| maxValue = (std::numeric_limits<int>::max)(); |
| m_leftLineEdit->setRange(minValue, maxValue); |
| m_rightLineEdit->setRange(minValue, maxValue); |
| |
| update(); |
| } |
| |
| |
| |
| void IntPairField::getRange(int &minValue, int &maxValue) |
| { |
| minValue = m_minValue; |
| maxValue = m_maxValue; |
| } |
| |
| |
| |
| void IntPairField::mousePressEvent(QMouseEvent *event) |
| { |
| if (event->button() == Qt::LeftButton) { |
| int x = event->pos().x(); |
| int cur0, cur1; |
| if (m_values.first > m_maxValue) |
| cur0 = value2pos(m_maxValue) - 5; |
| else |
| cur0 = value2pos(m_values.first); |
| if (m_values.second > m_maxValue) |
| cur1 = value2pos(m_maxValue); |
| else |
| cur1 = value2pos(m_values.second); |
| int d0 = abs(cur0 - x); |
| int d1 = abs(cur1 - x); |
| int d, cur; |
| if (d0 < d1 || (d0 == d1 && x < cur0)) { |
| d = d0; |
| cur = cur0; |
| m_grabIndex = 0; |
| } else { |
| d = d1; |
| cur = cur1; |
| m_grabIndex = 1; |
| } |
| if (d < 6) |
| m_grabOffset = cur - x; |
| else { |
| m_grabOffset = 0; |
| setValue(pos2value(x)); |
| emit valuesChanged(true); |
| update(); |
| } |
| } |
| } |
| |
| |
| |
| void IntPairField::mouseMoveEvent(QMouseEvent *event) |
| { |
| if (event->buttons()) { |
| std::pair<int, int> oldValues = m_values; |
| int x = event->pos().x() + m_grabOffset; |
| setValue(pos2value(x)); |
| if (oldValues == m_values) |
| return; |
| |
| emit valuesChanged(true); |
| update(); |
| } |
| } |
| |
| |
| |
| void IntPairField::mouseReleaseEvent(QMouseEvent *event) |
| { |
| m_grabOffset = 0; |
| m_grabIndex = 0; |
| emit valuesChanged(false); |
| } |
| |
| |
| |
| void IntPairField::onLeftEditingFinished() |
| { |
| int value = m_leftLineEdit->getValue(); |
| if (value == m_values.first) |
| return; |
| if (!m_isMaxRangeLimited && value < m_minValue) |
| value = m_minValue; |
| else if (m_isMaxRangeLimited) |
| value = tcrop(value, m_minValue, m_maxValue); |
| m_values.first = value; |
| if (m_values.first > m_values.second) { |
| m_values.second = m_values.first; |
| m_rightLineEdit->setValue(m_values.second); |
| } |
| emit valuesChanged(false); |
| update(); |
| } |
| |
| |
| |
| void IntPairField::onRightEditingFinished() |
| { |
| int value = m_rightLineEdit->getValue(); |
| if (value == m_values.second) |
| return; |
| if (m_isMaxRangeLimited) |
| value = tcrop(value, m_minValue, m_maxValue); |
| m_values.second = value; |
| if (m_values.second < m_values.first) { |
| m_values.first = m_values.second; |
| m_leftLineEdit->setValue(m_values.first); |
| } |
| emit valuesChanged(false); |
| update(); |
| } |
| |