src/RangedSlider.cpp

changeset 97
8283bbf95806
parent 96
c36fef8bb088
child 99
053c0578cf58
--- a/src/RangedSlider.cpp	Thu Mar 31 17:16:44 2022 +0200
+++ b/src/RangedSlider.cpp	Thu Mar 31 23:10:57 2022 +0200
@@ -40,21 +40,19 @@
 
 RangedSlider::RangedSlider(QWidget* parent)
    : QWidget(parent),
-     _min(0.0),
-     _max(1.0),
-     _prefMin(0.25),
-     _prefMax(0.75),
-     _val(0.5),
-     _prec(3),
-     _tickInterval(0),
-     _secondaryTicks(1),
-     _tooltipText(""),
-     _bgBrush(QColor(255,255,255)),
-     _prefRangeBrush(QColor(0,0,0)),
-     _prefRangePen(Qt::NoPen),
-     _markerBrush(QColor(255,255,255)),
-     _markerTextIsValue(false),
-     indicatorTextFont("Arial",
+    _min(0.0),
+    _max(1.0),
+    _prefMin(0.25),
+    _prefMax(0.75),
+    _val(0.5),
+    _prec(3),
+    _tooltipText(""),
+    _bgBrush(QColor(255,0,0)),
+    _prefRangeBrush(QColor(0,127,0)),
+    _prefRangePen(Qt::NoPen),
+    _markerBrush(QColor(255,255,255)),
+    _markerTextIsValue(false),
+    indicatorTextFont("Arial",
                        10,
                        QFont::Normal) // Previously we just did the indicator text in 'default' font
 {
@@ -74,96 +72,86 @@
    this->repaint();
 }
 
-void RangedSlider::setPreferredRange( double min, double max )
+/**
+ * @brief Set the normal limits in the _prexXxx values and calculate
+ *        the real drawing limits so that we can see if a value is slightly
+ *        out of range.
+ */
+void RangedSlider::setRange( double min, double max )
 {
-   _prefMin = min;
-   _prefMax = max;
+    _prefMin = min;
+    _prefMax = max;
+    // Calculate the outer limits
+    _min = _prefMin - ((_prefMax - _prefMin) * 0.2);
+    _max = _prefMax + ((_prefMax - _prefMin) * 0.2);
 
-   // Only show tooltips if the range has nonzero size.
-   setMouseTracking(min < max);
+    // Set the tooltip with the ranges.
+    _tooltipText = QString("%1 - %2").arg(min, 0, 'f', _prec).arg(max, 0, 'f', _prec);
 
-   _tooltipText = QString("%1 - %2").arg(min, 0, 'f', _prec).arg(max, 0, 'f', _prec);
-
-   update();
+    update();
 }
 
-void RangedSlider::setPreferredRange(QPair<double,double> minmax)
-{
-   setPreferredRange( minmax.first, minmax.second );
-}
-
-void RangedSlider::setRange( double min, double max )
-{
-   _min = min;
-   _max = max;
-   update();
-}
 
 void RangedSlider::setRange(QPair<double,double> minmax)
 {
    setRange( minmax.first, minmax.second );
 }
 
+
 void RangedSlider::setValue(double value)
 {
-   _val = value;
-//   _valText = QString("%1").arg(_val, 0, 'f', _prec);
-   update();
+    _val = value;
+
+    if (_val < _min)
+	_val = _min;
+    if (_val > _max)
+	_val = _max;
 
-   // See comment in constructor for why we call this here
-   this->setSizes();
-   return;
+    if (_markerTextIsValue) {
+	_markerText = QString("%1").arg(value, 0, 'f', _prec);
+	qDebug() << _markerText;
+    }
+
+    update();
+
+    // See comment in constructor for why we call this here
+    //this->setSizes();
+    return;
 }
 
+
 void RangedSlider::setPrecision(int precision)
 {
-   _prec = precision;
-   update();
+    _prec = precision;
+    update();
 }
 
+
 void RangedSlider::setBackgroundBrush( QBrush const& brush )
 {
-   _bgBrush = brush;
-   update();
+    _bgBrush = brush;
+    update();
 }
 
-void RangedSlider::setPreferredRangeBrush( QBrush const& brush )
-{
-   _prefRangeBrush = brush;
-   update();
-}
-
-void RangedSlider::setPreferredRangePen( QPen const& pen )
-{
-   _prefRangePen = pen;
-   update();
-}
 
 void RangedSlider::setMarkerBrush( QBrush const& brush )
 {
-   _markerBrush = brush;
-   update();
+    _markerBrush = brush;
+    update();
 }
 
 void RangedSlider::setMarkerText( QString const& text )
 {
-   _markerText = text;
-   update();
+    _markerText = text;
+    update();
 }
 
 void RangedSlider::setMarkerTextIsValue(bool val)
 {
-   _markerTextIsValue = val;
-   update();
+    _markerTextIsValue = val;
+    update();
 }
 
-void RangedSlider::setTickMarks( double primaryInterval, int secondaryTicks )
-{
-   _secondaryTicks = (secondaryTicks<1)? 1 : secondaryTicks;
-   _tickInterval = primaryInterval/_secondaryTicks;
-
-   update();
-}
 
 void RangedSlider::recalculateHeightInPixels() const {
    //
@@ -209,16 +197,16 @@
    // assumptions about space below the baseline are locale-specific, so, say, using ascent() instead of lineSpacing()
    // could end up painting us into a corner.
    //
-   QFontMetrics indicatorTextFontMetrics(this->indicatorTextFont);
-//   QFontMetrics valueTextFontMetrics(this->valueTextFont);
-   this->heightInPixels = indicatorTextFontMetrics.lineSpacing()/* + valueTextFontMetrics.lineSpacing()*/;
+   //QFontMetrics indicatorTextFontMetrics(this->indicatorTextFont);
+   this->heightInPixels = this->height(); //indicatorTextFontMetrics.lineSpacing();
    return;
 }
 
 void RangedSlider::setSizes() {
    // Caller's responsibility to have recently called this->recalculateHeightInPixels().  (See comment in that function
    // for how we choose minimum width.)
-   this->setMinimumSize(2 * this->heightInPixels, this->heightInPixels);
+//   this->setMinimumSize(2 * this->heightInPixels, this->heightInPixels);
+   this->setMinimumSize(60, 20);
 
    this->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
 
@@ -237,41 +225,32 @@
 
 void RangedSlider::mouseMoveEvent(QMouseEvent* event)
 {
-   event->accept();
+    event->accept();
 
-   QPoint tipPoint( mapToGlobal(QPoint(0,0)) );
-   QToolTip::showText( tipPoint, _tooltipText, this );
+    QPoint tipPoint( mapToGlobal(QPoint(0,0)) );
+    QToolTip::showText( tipPoint, _tooltipText, this );
 }
 
+
 void RangedSlider::paintEvent(QPaintEvent* event)
 {
    //
    // Simplistically, the high-level layout of the slider is:
    //
-   //    |-------------------------------------------------------------|
-   //    |                   Indicator text               | B L A N K  |
-   //    |------------------------------------------------+------------|
+   //    |------------------------------------------------|
    //    | <--------------- Graphical Area -------------> |
    //    |------------------------------------------------|
    //
    // The graphical area has:
    //  - a background rectangle of the full width of the area, representing the range from this->_min to this->_max
    //  - a foreground rectangle showing the sub-range of this background from this->_prefMin to this->_prefMax
-   //  - a line ("the indicator") showing where this->_val lies in the (this->_min to this->_max) range
+   //  - a vertical line ("the indicator") showing where this->_val lies in the (this->_min to this->_max) range
    //
-   // The indicator text sits above the indicator line and shows either its value (this->_valText) or some textual
+   // The indicator text sits on the center of the area and shows either its value (this->_valText) or some textual
    // description (eg "Slightly Malty" on the IBU/GU scale) which comes from this->_markerText.
    //
-   // In principle, we could have the value text a slightly different height than the graphical area - eg to help
-   // squeeze into smaller available vertical space on small screens (as we know there is blank space of
-   // indicatorTextHeight pixels above the space for the value text).
-   //
-   // The value text also shows this->_valText.
-   //
 
-   QFontMetrics indicatorTextFontMetrics(this->indicatorTextFont);
-   int indicatorTextHeight = indicatorTextFontMetrics.lineSpacing();
-   int graphicalAreaHeight = this->height() - indicatorTextHeight;
+   int graphicalAreaHeight = this->height();
 
    // Although the Qt calls take an x- and a y- radius, we want the radius on the rectangle corners to be the same
    // vertically and horizontally, so only define one measure here.
@@ -295,7 +274,7 @@
    QPainter painter(this);
 
    // Work out the left-to-right (ie x-coordinate) positions of things in the graphical area
-   double graphicalAreaWidth  = this->width()/* - valueTextWidth*/;
+   double graphicalAreaWidth  = this->width();
    double range               = this->_max - this->_min;
    double fgRectLeft          = graphicalAreaWidth * ((this->_prefMin - this->_min    )/range);
    double fgRectWidth         = graphicalAreaWidth * ((this->_prefMax - this->_prefMin)/range);
@@ -308,88 +287,53 @@
    indicatorLineMiddle = qBound(0.0, indicatorLineMiddle, graphicalAreaWidth - (indicatorLineWidth / 2));
    indicatorLineLeft   = qBound(0.0, indicatorLineLeft,   graphicalAreaWidth - indicatorLineWidth);
 
-   // The left-to-right position of the indicator text (also known as marker text) depends on where the slider is.
-   // First we ask the painter what size rectangle it will need to display this text
-   painter.setPen(indicatorTextColor);
-   painter.setFont(this->indicatorTextFont);
-   QRectF indicatorTextRect = painter.boundingRect(QRectF(), Qt::AlignCenter | Qt::AlignBottom, this->_markerText);
-
-   // Then we use the size of this rectangle to try to make the middle of the text sit over the indicator marker on
-   // the slider - but bounding things so that the text doesn't go off the edge of the slider.
-   double indicatorTextLeft = qBound(0.0,
-                                    indicatorLineMiddle - (indicatorTextRect.width() / 2),
-                                    graphicalAreaWidth - indicatorTextRect.width());
-
-   // Now we can draw the indicator text
-   painter.drawText(
-      indicatorTextLeft, 0,
-      indicatorTextRect.width(), indicatorTextRect.height(),
-      Qt::AlignCenter | Qt::AlignBottom, this->_markerText
-   );
-
    // All the rest of what we need to do is inside the graphical area, so move the origin to the top-left corner of it
-   painter.translate(0, indicatorTextRect.height());
+   painter.translate(0, 0);
    painter.setPen(Qt::NoPen);
 
    // Make sure anything we draw "inside" the "glass rectangle" stays inside.
    QPainterPath clipRect;
-   clipRect.addRoundedRect( QRectF(0, 0, graphicalAreaWidth, graphicalAreaHeight),
-                            rectangleCornerRadius,
-                            rectangleCornerRadius );
+   clipRect.addRoundedRect( QRectF(0, 0, graphicalAreaWidth, graphicalAreaHeight), rectangleCornerRadius, rectangleCornerRadius );
    painter.setClipPath(clipRect);
 
    // Draw the background rectangle.
    painter.setBrush(_bgBrush);
    painter.setRenderHint(QPainter::Antialiasing);
-   painter.drawRoundedRect( QRectF(0, 0, graphicalAreaWidth, graphicalAreaHeight),
-                            rectangleCornerRadius,
-                            rectangleCornerRadius );
+   painter.drawRoundedRect( QRectF(0, 0, graphicalAreaWidth, graphicalAreaHeight), rectangleCornerRadius, rectangleCornerRadius );
    painter.setRenderHint(QPainter::Antialiasing, false);
 
    // Draw the style "foreground" rectangle.
    painter.save();
-      painter.setBrush(_prefRangeBrush);
-      painter.setPen(_prefRangePen);
-      painter.setRenderHint(QPainter::Antialiasing);
-      painter.drawRoundedRect( QRectF(fgRectLeft, 0, fgRectWidth, graphicalAreaHeight),
-                               rectangleCornerRadius,
-                               rectangleCornerRadius );
+   painter.setBrush(_prefRangeBrush);
+   painter.setPen(_prefRangePen);
+   painter.setRenderHint(QPainter::Antialiasing);
+   painter.drawRoundedRect( QRectF(fgRectLeft, 0, fgRectWidth, graphicalAreaHeight), rectangleCornerRadius, rectangleCornerRadius );
    painter.restore();
 
    // Draw the indicator.
    painter.setBrush(_markerBrush);
    painter.drawRect( QRectF(indicatorLineLeft, 0, indicatorLineWidth, graphicalAreaHeight) );
 
-   // Draw a white-to-clear gradient to suggest "glassy."
-   painter.setBrush(glassBrush);
-   painter.setRenderHint(QPainter::Antialiasing);
-   painter.drawRoundedRect( QRectF(0, 0, graphicalAreaWidth, graphicalAreaHeight),
-                            rectangleCornerRadius,
-                            rectangleCornerRadius );
-   painter.setRenderHint(QPainter::Antialiasing, false);
+    // Draw a white-to-clear gradient to suggest "glassy."
+    painter.setBrush(glassBrush);
+    painter.setRenderHint(QPainter::Antialiasing);
+    painter.drawRoundedRect( QRectF(0, 0, graphicalAreaWidth, graphicalAreaHeight), rectangleCornerRadius, rectangleCornerRadius );
+    painter.setRenderHint(QPainter::Antialiasing, false);
 
-   // Draw the ticks.
-   painter.setPen(Qt::black);
-   if( _tickInterval > 0.0 )
-   {
-      int secTick = 1;
-      for( double currentTick = _min+_tickInterval; _max - currentTick > _tickInterval-1e-6; currentTick += _tickInterval )
-      {
-         painter.translate( graphicalAreaWidth/(_max-_min) * _tickInterval, 0);
-         if( secTick == _secondaryTicks )
-         {
-            painter.drawLine( QPointF(0,0.25*graphicalAreaHeight), QPointF(0,0.75*graphicalAreaHeight) );
-            secTick = 1;
-         }
-         else
-         {
-            painter.drawLine( QPointF(0,0.333*graphicalAreaHeight), QPointF(0,0.666*graphicalAreaHeight) );
-            ++secTick;
-         }
-      }
-   }
+    // Draw the _markerText in the center of the widget.
+    // First we ask the painter what size rectangle it will need to display this text
+    painter.setPen(indicatorTextColor);
+    painter.setFont(this->indicatorTextFont);
+    QRectF indicatorTextRect = painter.boundingRect(QRectF(), Qt::AlignCenter | Qt::AlignBottom, this->_markerText);
 
-   return;
+    // Then we use the size of this rectangle to try to calculate the X and Y position for the markerText.
+    double indicatorTextX = (graphicalAreaWidth - indicatorTextRect.width()) / 2;
+    double indicatorTextY = (graphicalAreaHeight - indicatorTextRect.height()) / 2;
+
+    // Now we can draw the indicator text
+    painter.drawText( indicatorTextX, indicatorTextY, indicatorTextRect.width(), indicatorTextRect.height(), Qt::AlignCenter | Qt::AlignBottom, this->_markerText);
+
+    return;
 }
 
 

mercurial