#include "stfslider.h" #include #include #include #include #include static float clamp(float x) { return std::min(std::max(x, 0.0f), 1.0f); } STFSlider::STFSlider(const QColor &color, QWidget *parent) : QWidget(parent) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setMinimumWidth(100); setMouseTracking(true); if(color == Qt::white) { setMaximumHeight(16); setMinimumHeight(16); } else { setMaximumHeight(10); setMinimumHeight(10); } m_blackPoint = 0; m_midPoint = 0.5; m_whitePoint = 1; m_grabbed = -1; m_fineTune = false; m_color = color; if(color == Qt::blue || color == Qt::red) m_threshold = 1.1f; else if(color == Qt::green) m_threshold = 0.8f; else m_threshold = 0.4f; setToolTip(tr("Press Shift for fine tuning")); } float STFSlider::blackPoint() const { return m_blackPoint; } float STFSlider::midPoint() const { return m_midPoint; } float STFSlider::whitePoint() const { return m_whitePoint; } void STFSlider::setMTFParams(float low, float mid, float high) { m_blackPoint = clamp(low); m_midPoint = clamp(mid); m_whitePoint = clamp(high); update(); } void STFSlider::orientationChanged(Qt::Orientations orientation) { m_orientation = orientation; if(m_orientation == Qt::Horizontal) { if(m_color == Qt::white) { setMaximumSize(QWIDGETSIZE_MAX, 16); setMinimumSize(16, 16); } else { setMaximumSize(QWIDGETSIZE_MAX, 10); setMinimumSize(10, 10); } } else { if(m_color == Qt::white) { setMaximumSize(16, QWIDGETSIZE_MAX); setMinimumSize(16, 16); } else { setMaximumSize(10, QWIDGETSIZE_MAX); setMinimumSize(10, 10); } } } void STFSlider::paintEvent(QPaintEvent *event) { QPainter painter(this); QRect rect = event->rect(); qreal w = rect.width() - 1; qreal h = rect.height(); if(m_orientation == Qt::Vertical) { rect = rect.transposed(); painter.rotate(90); w = rect.width() - 1; h = rect.height(); painter.translate(0, -h); } QLinearGradient gradient(rect.topLeft(), rect.topRight()); gradient.setColorAt(0, Qt::black); for(int i=1; i<=32; i++) { qreal p = i/32.0f; qreal c = std::pow(p, 1.0/2.2)*255; gradient.setColorAt(p, QColor(m_color.redF()*c, m_color.greenF()*c, m_color.blueF()*c)); } QPainterPath tick(QPointF(0, 0)); tick.lineTo(0, h - 5); tick.lineTo(-5, h); tick.lineTo(5, h); tick.lineTo(0, h - 5); painter.setBrush(gradient); painter.setPen(Qt::NoPen); painter.drawRect(rect); auto drawTick = [&](qreal p) { painter.setPen(p < m_threshold ? Qt::white : Qt::black); painter.resetTransform(); if(m_orientation == Qt::Vertical) { painter.rotate(90); painter.translate(0, -h); } painter.translate(w*p, 0); painter.drawPath(tick); }; painter.setBrush(Qt::NoBrush); drawTick(m_blackPoint); drawTick(m_blackPoint + (m_whitePoint - m_blackPoint) * m_midPoint); drawTick(m_whitePoint); } void STFSlider::mouseMoveEvent(QMouseEvent *event) { qreal x,w; if(m_orientation == Qt::Horizontal) { x = event->position().x(); w = width(); } else { x = event->position().y(); w = height(); } if(std::abs(m_blackPoint*w - x) < 5 || std::abs((m_blackPoint + (m_whitePoint - m_blackPoint) * m_midPoint)*w - x) < 5 || std::abs(m_whitePoint*w - x) < 5) setCursor(m_orientation == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor); else unsetCursor(); qreal xw = x/w; if(event->modifiers() & Qt::ShiftModifier && !m_fineTune) { m_fineTune = true; m_fineTuneX = xw; } if(!(event->modifiers() & Qt::ShiftModifier) && m_fineTune) m_fineTune = false; if(m_fineTune) { xw = m_fineTuneX + (xw - m_fineTuneX) * 0.2; } switch(m_grabbed) { case 0: m_blackPoint = clamp(xw); m_whitePoint = std::max(m_whitePoint, m_blackPoint); QToolTip::showText(event->globalPosition().toPoint(), QString::number(m_blackPoint), this); break; case 1: m_midPoint = (xw - m_blackPoint) / (m_whitePoint - m_blackPoint); m_midPoint = clamp(m_midPoint); QToolTip::showText(event->globalPosition().toPoint(), QString::number(m_midPoint), this); break; case 2: m_whitePoint = clamp(xw); m_blackPoint = std::min(m_blackPoint, m_whitePoint); QToolTip::showText(event->globalPosition().toPoint(), QString::number(m_whitePoint), this); break; } if(m_grabbed >= 0) { emit paramChanged(m_blackPoint, midPoint(), m_whitePoint); update(); } } void STFSlider::mousePressEvent(QMouseEvent *event) { qreal x,w; if(m_orientation == Qt::Horizontal) { x = event->position().x(); w = width(); } else { x = event->position().y(); w = height(); } if(event->modifiers() & Qt::ShiftModifier) { m_fineTune = true; m_fineTuneX = x/w; } if(std::abs((m_blackPoint + (m_whitePoint - m_blackPoint) * m_midPoint)*w - x) < 5) m_grabbed = 1; else if(std::abs(m_blackPoint*w - x) < 5) m_grabbed = 0; else if(std::abs(m_whitePoint*w - x) < 5) m_grabbed = 2; else m_grabbed = -1; } void STFSlider::mouseReleaseEvent(QMouseEvent *) { m_grabbed = -1; m_fineTune = false; emit paramChanged(m_blackPoint, midPoint(), m_whitePoint); }