From 0067cdfd8fa1e051f3360e07fd521f6a9ab54181 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Sun, 7 Nov 2021 09:22:57 +0100 Subject: [PATCH] only move knob when drawing along the arc --- examples/iotdashboard/LightDisplay.cpp | 47 ++++++++++++++++++++++++-- examples/iotdashboard/LightDisplay.h | 2 ++ examples/iotdashboard/Skin.cpp | 4 +-- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/examples/iotdashboard/LightDisplay.cpp b/examples/iotdashboard/LightDisplay.cpp index b2b3fdb9..c613b7f4 100644 --- a/examples/iotdashboard/LightDisplay.cpp +++ b/examples/iotdashboard/LightDisplay.cpp @@ -6,8 +6,11 @@ #include "LightDisplay.h" #include "Skin.h" +#include #include +#include + QSK_SUBCONTROL( LightDisplay, Panel ) QSK_SUBCONTROL( LightDisplay, Groove ) QSK_SUBCONTROL( LightDisplay, ColdAndWarmArc ) @@ -88,11 +91,17 @@ void LightDisplay::mouseMoveEvent( QMouseEvent* event ) if ( !isPressed() ) return; - // ### check if arc contains the position - const auto mousePos = qskMousePosition( event ); const auto rect = subControlRect( ColdAndWarmArc ); + bool arcContainsMousePos = arcContainsPoint( rect, mousePos ); + + if( !arcContainsMousePos ) + { + setSkinStateFlag( Pressed, false ); + return; + } + const qreal ratioX = ( mousePos.x() - rect.x() ) / rect.width(); setValueAsRatio( ratioX ); @@ -103,4 +112,38 @@ void LightDisplay::mouseReleaseEvent( QMouseEvent* /*event*/ ) setSkinStateFlag( Pressed, false ); } +bool LightDisplay::arcContainsPoint( const QRectF& rect, const QPointF& point ) const +{ + // putting this in an own function just because it might be useful + // at other places in the future + + const QskArcMetrics metrics = arcMetricsHint( ColdAndWarmArc ); + const int tolerance = 10; + + // 1. check angle + QPointF circlePos( point.x() - rect.center().x(), + rect.center().y() - point.y() ); + + const qreal atan = qAtan2( circlePos.y(), circlePos.x() ); + const qreal angle = qRadiansToDegrees( atan ); + // the qAbs() actually only works for the 180 degrees case, + // we might want to generalize this later: + const bool angleWithinRange = ( qAbs( angle ) + tolerance ) > metrics.startAngle() + && qAbs( angle ) < ( metrics.startAngle() + metrics.spanAngle() - tolerance ); + + // 2. check whether point is on arc + const qreal radiusMax = rect.width() / 2; + const qreal arcWidth = metrics.width(); + const qreal radiusMin = radiusMax - arcWidth; + + const qreal polarRadius = qSqrt( qPow( circlePos.x(), 2 ) + qPow( circlePos.y(), 2 ) ); + const bool pointOnArc = ( polarRadius + tolerance ) > radiusMin + && ( polarRadius - tolerance ) < radiusMax; + + qDebug() << angleWithinRange << angle << pointOnArc; + bool ret = angleWithinRange && pointOnArc; + + return ret; +} + #include "moc_LightDisplay.cpp" diff --git a/examples/iotdashboard/LightDisplay.h b/examples/iotdashboard/LightDisplay.h index ba62c7ac..4f121a03 100644 --- a/examples/iotdashboard/LightDisplay.h +++ b/examples/iotdashboard/LightDisplay.h @@ -37,6 +37,8 @@ class LightDisplay : public QskBoundedValueInput void mouseReleaseEvent( QMouseEvent* e ) override; private: + bool arcContainsPoint( const QRectF&, const QPointF& ) const; + QskShadowMetrics m_shadow; QColor m_shadowColor = Qt::black; diff --git a/examples/iotdashboard/Skin.cpp b/examples/iotdashboard/Skin.cpp index eaff08cc..1b03452e 100644 --- a/examples/iotdashboard/Skin.cpp +++ b/examples/iotdashboard/Skin.cpp @@ -184,7 +184,7 @@ void Skin::initHints( const Palette& palette ) // light intensity: ed.setBoxShape( LightDisplay::Panel, 100, Qt::RelativeSize ); - ed.setArcMetrics( LightDisplay::ColdAndWarmArc, 8.785, 0, 0 ); + ed.setArcMetrics( LightDisplay::ColdAndWarmArc, 8.785, 0, 180 * 16 ); QskGradient coldGradient( Qt::Horizontal, { { 0.0, 0xffff3122 }, { 0.2, 0xfffeeeb7 }, { 0.3, 0xffa7b0ff }, @@ -195,7 +195,7 @@ void Skin::initHints( const Palette& palette ) ed.setFontRole( LightDisplay::ValueText, QskSkin::LargeFont ); ed.setColor( LightDisplay::ValueText, "#929cb2" ); - ed.setStrutSize( LightDisplay::Knob, { 15.65, 15.65 } ); + ed.setStrutSize( LightDisplay::Knob, { 20, 20 } ); ed.setBoxBorderMetrics( LightDisplay::Knob, 1 ); ed.setBoxBorderColors( LightDisplay::Knob, 0xffc4c4c4 ); ed.setBoxShape( LightDisplay::Knob, 100, Qt::RelativeSize );