diff --git a/src/widget/wslidercomposed.cpp b/src/widget/wslidercomposed.cpp index 8adeae227a69..a998ebc9a1b4 100644 --- a/src/widget/wslidercomposed.cpp +++ b/src/widget/wslidercomposed.cpp @@ -23,6 +23,7 @@ #include "widget/controlwidgetconnection.h" #include "widget/wpixmapstore.h" +#include "widget/wskincolor.h" #include "util/debug.h" #include "util/duration.h" #include "util/math.h" @@ -33,6 +34,17 @@ WSliderComposed::WSliderComposed(QWidget * parent) m_dHandleLength(0.0), m_dSliderLength(0.0), m_bHorizontal(false), + m_dBarWidth(0.0), + m_dBarBgWidth(0.0), + m_dBarStart(0.0), + m_dBarEnd(0.0), + m_dBarBgStart(0.0), + m_dBarBgEnd(0.0), + m_dBarAxisPos(0.0), + m_bBarUnipolar(true), + m_barColor(nullptr), + m_barBgColor(nullptr), + m_barPenCap(Qt::FlatCap), m_pSlider(nullptr), m_pHandle(nullptr), m_renderTimer(mixxx::Duration::fromMillis(20), @@ -49,6 +61,7 @@ void WSliderComposed::setup(const QDomNode& node, const SkinContext& context) { // Setup pixmaps unsetPixmaps(); + double scaleFactor = context.getScaleFactor(); QDomElement slider = context.selectElement(node, "Slider"); if (!slider.isNull()) { // The implicit default in <1.12.0 was FIXED so we keep it for backwards @@ -57,7 +70,7 @@ void WSliderComposed::setup(const QDomNode& node, const SkinContext& context) { setSliderPixmap( sourceSlider, context.selectScaleMode(slider, Paintable::FIXED), - context.getScaleFactor()); + scaleFactor); } m_dSliderLength = m_bHorizontal ? width() : height(); @@ -70,7 +83,66 @@ void WSliderComposed::setup(const QDomNode& node, const SkinContext& context) { // compatibility. setHandlePixmap(h, sourceHandle, context.selectScaleMode(handle, Paintable::FIXED), - context.getScaleFactor()); + scaleFactor); + + // Set up the level bar. + QColor barColor = context.selectColor(node, "BarColor"); + context.hasNodeSelectDouble(node, "BarWidth", &m_dBarWidth); + if (barColor.isValid() && m_dBarWidth > 0.0) { + m_barColor = WSkinColor::getCorrectColor(barColor); + m_dBarWidth *= scaleFactor; + QString margins; + QString bgMargins; + if (context.hasNodeSelectString(node, "BarMargins", &margins)) { + int comma = margins.indexOf(","); + bool m1ok; + bool m2ok; + double m1 = (margins.left(comma)).toDouble(&m1ok); + double m2 = (margins.mid(comma + 1)).toDouble(&m2ok); + if (m1ok && m2ok) { + m_dBarStart = m1 * scaleFactor; + m_dBarEnd = m2 * scaleFactor; + } + } + + // Set up the bar background if there's a valid color set. + // If the background width and margins are not set explicitly + // we simply adopt the settings of the level bar. + QColor barBgColor = context.selectColor(node, "BarBgColor"); + if (barBgColor.isValid()) { + m_barBgColor = WSkinColor::getCorrectColor(barBgColor); + if (context.hasNodeSelectDouble(node, "BarBgWidth", &m_dBarBgWidth)) { + if (m_dBarBgWidth > 0.0) { + m_dBarBgWidth *= scaleFactor; + } + } else { + m_dBarBgWidth = m_dBarWidth; + } + if (context.hasNodeSelectString(node, "BarBgMargins", &bgMargins)) { + int comma = bgMargins.indexOf(","); + bool m1ok; + bool m2ok; + double m1 = (bgMargins.left(comma)).toDouble(&m1ok); + double m2 = (bgMargins.mid(comma + 1)).toDouble(&m2ok); + if (m1ok && m2ok) { + m_dBarBgStart = m1 * scaleFactor; + m_dBarBgEnd = m2 * scaleFactor; + } + } else { + m_dBarBgStart = m_dBarStart; + m_dBarBgEnd = m_dBarEnd; + } + } + // Shift the bar center line to the right or to the bottom (horizontal sliders) + if (context.hasNodeSelectDouble(node, "BarAxisPos", &m_dBarAxisPos)) { + m_dBarAxisPos *= scaleFactor; + } + // Draw the bar from 0 by default, from bottom or from left (horizontal) + m_bBarUnipolar = context.selectBool(node, "BarUnipolar", true); + if (context.selectBool(node, "BarRoundCaps", false)) { + m_barPenCap = Qt::RoundCap; + } + } QString eventWhileDrag; if (context.hasNodeSelectString(node, "EventWhileDrag", &eventWhileDrag)) { @@ -154,19 +226,84 @@ void WSliderComposed::paintEvent(QPaintEvent * /*unused*/) { m_pSlider->draw(rect(), &p); } + // Draw level bar underneath handle + if (m_barColor.isValid() && m_dBarWidth > 0.0) { + drawBar(&p); + } + if (!m_pHandle.isNull() && !m_pHandle->isNull()) { // Slider position rounded, verify this for HiDPI : bug 1479037 double drawPos = round(m_handler.parameterToPosition(getControlParameterDisplay())); + QRectF targetRect; if (m_bHorizontal) { // The handle's draw mode determines whether it is stretched. - QRectF targetRect(drawPos, 0, m_dHandleLength, height()); - m_pHandle->draw(targetRect, &p); + targetRect = QRectF(drawPos, 0, m_dHandleLength, height()); } else { // The handle's draw mode determines whether it is stretched. - QRectF targetRect(0, drawPos, width(), m_dHandleLength); - m_pHandle->draw(targetRect, &p); + targetRect = QRectF(0, drawPos, width(), m_dHandleLength); + } + m_pHandle->draw(targetRect, &p); + } +} + +void WSliderComposed::drawBar(QPainter* pPainter) { + double x1; + double x2; + double y1; + double y2; + double value; + + // Draw bar background + if (m_dBarBgWidth > 0.0) { + QPen barBgPen = QPen(m_barBgColor); + barBgPen.setWidth(m_dBarBgWidth); + barBgPen.setCapStyle(m_barPenCap); + pPainter->setPen(barBgPen); + QLineF barBg; + if (m_bHorizontal) { + barBg = QLineF(m_dBarBgStart, m_dBarAxisPos, + width() - m_dBarBgEnd, m_dBarAxisPos); + } else { + barBg = QLineF(m_dBarAxisPos, height() - m_dBarBgEnd, + m_dBarAxisPos, m_dBarBgStart); + } + pPainter->drawLine(barBg); + } + + QPen barPen = QPen(m_barColor); + barPen.setWidth(m_dBarWidth); + barPen.setCapStyle(m_barPenCap); + pPainter->setPen(barPen); + + if (m_bHorizontal) { + // Left to right increases the parameter + value = getControlParameterDisplay(); + if (m_bBarUnipolar) { + // draw from the left + x1 = m_dBarStart; + } else { + // draw from center + x1 = m_dBarStart + (width() - m_dBarStart -m_dBarEnd) / 2; + } + x2 = m_dBarStart + value * (width() - m_dBarStart - m_dBarEnd); + y1 = m_dBarAxisPos; + y2 = y1; + } else { // vertical slider + // Sliders usually increase parameters when moved UP, but pixels + // are count top to bottom, so we flip the scale + value = 1.0 - getControlParameterDisplay(); + x1 = m_dBarAxisPos; + x2 = x1; + if (m_bBarUnipolar) { + // draw from bottom + y1 = height() - m_dBarEnd; + } else { + // draw from center + y1 = m_dBarEnd + (height() - m_dBarStart - m_dBarEnd) / 2; } + y2 = m_dBarStart + value * (height() - m_dBarStart - m_dBarEnd); } + pPainter->drawLine(x1, y1, x2, y2); } void WSliderComposed::resizeEvent(QResizeEvent* pEvent) { diff --git a/src/widget/wslidercomposed.h b/src/widget/wslidercomposed.h index 0da485131368..87370facc709 100644 --- a/src/widget/wslidercomposed.h +++ b/src/widget/wslidercomposed.h @@ -66,6 +66,7 @@ class WSliderComposed : public WWidget { void mouseReleaseEvent(QMouseEvent* e) override; void mousePressEvent(QMouseEvent* e) override; void paintEvent(QPaintEvent* e) override; + void drawBar(QPainter* pPainter); void wheelEvent(QWheelEvent* e) override; void resizeEvent(QResizeEvent* pEvent) override; @@ -81,6 +82,18 @@ class WSliderComposed : public WWidget { double m_dSliderLength; // True if it's a horizontal slider bool m_bHorizontal; + // Properties to draw the level bar + double m_dBarWidth; + double m_dBarBgWidth; + double m_dBarStart; + double m_dBarEnd; + double m_dBarBgStart; + double m_dBarBgEnd; + double m_dBarAxisPos; + bool m_bBarUnipolar; + QColor m_barColor; + QColor m_barBgColor; + Qt::PenCapStyle m_barPenCap; // Pointer to pixmap of the slider PaintablePointer m_pSlider; // Pointer to pixmap of the handle