Speedometer: Make it skinnable

This commit is contained in:
Peter Hartmann 2018-05-07 13:28:57 +02:00
parent 41d97c8c91
commit 847500fb7c
5 changed files with 89 additions and 29 deletions

View File

@ -74,7 +74,7 @@ namespace {
return font; return font;
} }
} } // namespace
DefaultSkin::DefaultSkin( const QString& name, QObject* parent ): DefaultSkin::DefaultSkin( const QString& name, QObject* parent ):
QskSkin( parent ), QskSkin( parent ),
@ -101,7 +101,8 @@ void DefaultSkin::initHints()
setColor( QskTextLabel::Text, m_palette->color4 ); setColor( QskTextLabel::Text, m_palette->color4 );
// - sound control // -- sound control
setGradient( SoundControl::Overlay, 0 ); setGradient( SoundControl::Overlay, 0 );
setGradient( SoundControl::CrossHair, m_palette->color3 ); setGradient( SoundControl::CrossHair, m_palette->color3 );
setGradient( SoundControl::Marker, m_palette->color5 ); setGradient( SoundControl::Marker, m_palette->color5 );
@ -146,6 +147,30 @@ void DefaultSkin::initHints()
setBoxShape( QskSlider::Handle, 100.0, Qt::RelativeSize ); setBoxShape( QskSlider::Handle, 100.0, Qt::RelativeSize );
setGradient( QskSlider::Handle, m_palette->color5 ); setGradient( QskSlider::Handle, m_palette->color5 );
// -- speedometers
setBoxBorderMetrics( Speedometer::Panel, 2 );
setGradient( Speedometer::Panel, m_palette->color1 );
setBoxBorderColors( Speedometer::Panel, m_palette->color3 );
setBoxBorderMetrics( Speedometer::NeedleHead, 2 );
setMetric( Speedometer::NeedleHead | QskAspect::Size, 15 );
setGradient( Speedometer::NeedleHead, QskGradient( QskGradient::Diagonal,
m_palette->color2, m_palette->color1 ) );
// setBoxBorderColors( Speedometer::NeedleHead, m_palette->color4 );
setMetric( Speedometer::Needle | QskAspect::MinimumWidth, 2 );
setMetric( Speedometer::Needle | QskAspect::Margin, 10 );
setColor( Speedometer::Needle, m_palette->color2 );
// margins between numbers and ticks:
setMargins( Speedometer::Labels, QskMargins( 4, 4, 4, 4 ) );
setMetric( Speedometer::Labels | QskAspect::MinimumWidth, 2 );
setMetric( Speedometer::Labels | QskAspect::Size, 15 ); // ticks size
setColor( Speedometer::Labels, m_palette->color4 );
setFontRole( Speedometer::Labels, QskSkin::SmallFont );
// handle expanding, when being pressed // handle expanding, when being pressed
for ( auto state : { QskAspect::NoState, QskSlider::Pressed } ) for ( auto state : { QskAspect::NoState, QskSlider::Pressed } )
{ {

View File

@ -140,6 +140,29 @@ void OtherSkin::initHints()
setBoxBorderMetrics( QskSlider::Handle, 0 ); setBoxBorderMetrics( QskSlider::Handle, 0 );
setBoxShape( QskSlider::Handle, 6 ); setBoxShape( QskSlider::Handle, 6 );
setGradient( QskSlider::Handle, m_palette->color3 ); setGradient( QskSlider::Handle, m_palette->color3 );
// -- speedometers
setBoxBorderMetrics( Speedometer::Panel, 5 );
setGradient( Speedometer::Panel, QskGradient( QskGradient::Vertical,
m_palette->color2, m_palette->color4 ) );
setBoxBorderColors( Speedometer::Panel, m_palette->color3 );
setBoxBorderMetrics( Speedometer::NeedleHead, 5 );
setMetric( Speedometer::NeedleHead | QskAspect::Size, 10 );
setGradient( Speedometer::NeedleHead, m_palette->color2 );
setBoxBorderColors( Speedometer::NeedleHead, m_palette->color4 );
setMetric( Speedometer::Needle | QskAspect::MinimumWidth, 4 );
setMetric( Speedometer::Needle | QskAspect::Margin, 15 );
setColor( Speedometer::Needle, m_palette->color4 );
// margins between numbers and ticks:
setMargins( Speedometer::Labels, QskMargins( 3, 3, 3, 3 ) );
setMetric( Speedometer::Labels | QskAspect::MinimumWidth, 3 );
setMetric( Speedometer::Labels | QskAspect::Size, 25 ); // ticks size
setColor( Speedometer::Labels, m_palette->color4 );
setFontRole( Speedometer::Labels, QskSkin::SmallFont );
} }
void OtherSkin::initGraphicFilters() void OtherSkin::initGraphicFilters()

View File

@ -5,6 +5,7 @@
QSK_SUBCONTROL( Speedometer, Panel ) QSK_SUBCONTROL( Speedometer, Panel )
QSK_SUBCONTROL( Speedometer, Labels ) QSK_SUBCONTROL( Speedometer, Labels )
QSK_SUBCONTROL( Speedometer, NeedleHead )
QSK_SUBCONTROL( Speedometer, Needle ) QSK_SUBCONTROL( Speedometer, Needle )
Speedometer::Speedometer( QQuickItem* parent ) : Speedometer::Speedometer( QQuickItem* parent ) :

View File

@ -8,7 +8,7 @@ class Speedometer : public QskRangeControl
Q_OBJECT Q_OBJECT
public: public:
QSK_SUBCONTROLS( Panel, Labels, Needle ) QSK_SUBCONTROLS( Panel, Labels, NeedleHead, Needle )
Speedometer( QQuickItem* parent = nullptr ); Speedometer( QQuickItem* parent = nullptr );

View File

@ -15,22 +15,24 @@
namespace namespace
{ {
class TicksNode : public QSGGeometryNode class TicksNode : public QSGGeometryNode
{ {
public: public:
TicksNode( const QColor& color ): TicksNode():
m_geometry( QSGGeometry::defaultAttributes_Point2D(), 0 ) m_geometry( QSGGeometry::defaultAttributes_Point2D(), 0 )
{ {
m_geometry.setDrawingMode( GL_LINES ); m_geometry.setDrawingMode( GL_LINES );
m_geometry.setVertexDataPattern( QSGGeometry::StaticPattern ); m_geometry.setVertexDataPattern( QSGGeometry::StaticPattern );
m_material.setColor( color );
setGeometry( &m_geometry ); setGeometry( &m_geometry );
setMaterial( &m_material ); setMaterial( &m_material );
} }
void setColor( const QColor& color )
{
m_material.setColor( color );
}
private: private:
QSGFlatColorMaterial m_material; QSGFlatColorMaterial m_material;
QSGGeometry m_geometry; QSGGeometry m_geometry;
@ -87,9 +89,9 @@ QSGNode* SpeedometerSkinlet::updatePanelNode( const Speedometer* speedometer, QS
QRectF panelRect = subControlRect( speedometer, Speedometer::Panel ); QRectF panelRect = subControlRect( speedometer, Speedometer::Panel );
qreal radius = panelRect.width() / 2; qreal radius = panelRect.width() / 2;
QskBoxShapeMetrics shapeMetrics( radius, radius, radius, radius ); QskBoxShapeMetrics shapeMetrics( radius, radius, radius, radius );
QskBoxBorderMetrics borderMetrics( 2 ); QskBoxBorderMetrics borderMetrics = speedometer->boxBorderMetricsHint( Speedometer::Panel );
QskBoxBorderColors borderColors( Qt::white ); QskBoxBorderColors borderColors = speedometer->boxBorderColorsHint( Speedometer::Panel );
QskGradient gradient( Qt::black ); QskGradient gradient = speedometer->gradientHint( Speedometer::Panel );
boxNode->setBoxData( panelRect, shapeMetrics, borderMetrics, borderColors, gradient ); boxNode->setBoxData( panelRect, shapeMetrics, borderMetrics, borderColors, gradient );
return boxNode; return boxNode;
@ -109,9 +111,12 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode( const Speedometer* speedometer, Q
if ( ticksNode == nullptr ) if ( ticksNode == nullptr )
{ {
ticksNode = new TicksNode( Qt::white ); ticksNode = new TicksNode();
} }
QColor color = speedometer->color( Speedometer::Labels );
ticksNode->setColor( color );
const auto startAngle = speedometer->minimum(); const auto startAngle = speedometer->minimum();
const auto endAngle = speedometer->maximum(); const auto endAngle = speedometer->maximum();
const auto step = ( endAngle - startAngle ) / ( labelsCount - 1 ); const auto step = ( endAngle - startAngle ) / ( labelsCount - 1 );
@ -130,10 +135,12 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode( const Speedometer* speedometer, Q
panelRect.y() + panelRect.height() / 2 ); panelRect.y() + panelRect.height() / 2 );
auto radius = static_cast< float >( panelRect.width() / 2 ); auto radius = static_cast< float >( panelRect.width() / 2 );
const QMarginsF numbersMargins = speedometer->marginsHint( Speedometer::Labels | QskAspect::Margin ); const QMarginsF numbersMargins = speedometer->marginsHint( Speedometer::Labels );
QFontMetrics fontMetrics( speedometer->effectiveFont( Speedometer::Labels ) ); QFontMetrics fontMetrics( speedometer->effectiveFont( Speedometer::Labels ) );
auto angle = startAngle; auto angle = startAngle;
qreal length = speedometer->metric( Speedometer::Labels | QskAspect::Size );
QVector< QString > labels = speedometer->labels();
// Create a series of tickmarks from minimum to maximum // Create a series of tickmarks from minimum to maximum
for( int i = 0; i < labelsCount; ++i, angle += step ) for( int i = 0; i < labelsCount; ++i, angle += step )
@ -145,7 +152,6 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode( const Speedometer* speedometer, Q
auto yStart = center.y() + radius * sine; auto yStart = center.y() + radius * sine;
// ### skin hint for each of highlighted / normal marks // ### skin hint for each of highlighted / normal marks
qreal length = 15;
auto xEnd = center.x() + ( radius - length ) * cosine; auto xEnd = center.x() + ( radius - length ) * cosine;
auto yEnd = center.y() + ( radius - length ) * sine; auto yEnd = center.y() + ( radius - length ) * sine;
@ -154,8 +160,6 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode( const Speedometer* speedometer, Q
vertexData += 2; vertexData += 2;
QVector< QString > labels = speedometer->labels();
// only create a text node if there is a label for it: // only create a text node if there is a label for it:
if ( labels.count() > i ) if ( labels.count() > i )
{ {
@ -182,8 +186,9 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode( const Speedometer* speedometer, Q
numbersNode = new QskTextNode(); numbersNode = new QskTextNode();
} }
numbersNode->setTextData( speedometer, text, numbersRect, QFont(), QFont font = speedometer->effectiveFont( Speedometer::Labels );
QskTextOptions(), QskTextColors( Qt::white ), numbersNode->setTextData( speedometer, text, numbersRect, font,
QskTextOptions(), QskTextColors( color ),
Qt::AlignCenter | Qt::AlignHCenter, Qsk::Normal ); Qt::AlignCenter | Qt::AlignHCenter, Qsk::Normal );
if ( ticksNode->childCount() <= i ) if ( ticksNode->childCount() <= i )
@ -194,7 +199,8 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode( const Speedometer* speedometer, Q
} }
} }
geometry->setLineWidth( 2 ); auto lineWidth = speedometer->metric( Speedometer::Labels | QskAspect::MinimumWidth );
geometry->setLineWidth( lineWidth );
geometry->markVertexDataDirty(); geometry->markVertexDataDirty();
ticksNode->markDirty( QSGNode::DirtyGeometry ); ticksNode->markDirty( QSGNode::DirtyGeometry );
@ -206,7 +212,7 @@ QSGNode* SpeedometerSkinlet::updateNeedleNode( const Speedometer* speedometer, Q
{ {
QMarginsF margins = speedometer->marginsHint( Speedometer::Panel | QskAspect::Margin ); QMarginsF margins = speedometer->marginsHint( Speedometer::Panel | QskAspect::Margin );
const QRectF panelRect = subControlRect( speedometer, Speedometer::Panel ).marginsRemoved( margins ); const QRectF panelRect = subControlRect( speedometer, Speedometer::Panel ).marginsRemoved( margins );
auto radius = 15; // ### skin hint auto radius = speedometer->metric( Speedometer::NeedleHead | QskAspect::Size );
QPointF center = QPointF( panelRect.x() + panelRect.width() / 2, QPointF center = QPointF( panelRect.x() + panelRect.width() / 2,
panelRect.y() + panelRect.height() / 2 ); panelRect.y() + panelRect.height() / 2 );
@ -217,38 +223,43 @@ QSGNode* SpeedometerSkinlet::updateNeedleNode( const Speedometer* speedometer, Q
boxNode = new QskBoxNode; boxNode = new QskBoxNode;
} }
QskBoxShapeMetrics shapeMetrics( radius, radius, radius, radius );
QskBoxBorderMetrics borderMetrics = speedometer->boxBorderMetricsHint( Speedometer::NeedleHead );
QskBoxBorderColors borderColors = speedometer->boxBorderColorsHint( Speedometer::NeedleHead );
QskGradient gradient = speedometer->gradientHint( Speedometer::NeedleHead );
QRectF centerNodeRect( center.x() - radius, center.y() - radius, QRectF centerNodeRect( center.x() - radius, center.y() - radius,
2 * radius, 2 * radius ); 2 * radius, 2 * radius );
QskBoxShapeMetrics shapeMetrics( radius, radius, radius, radius );
QskBoxBorderMetrics borderMetrics( 2 );
QskBoxBorderColors borderColors( Qt::red );
QskGradient gradient( Qt::red );
boxNode->setBoxData( centerNodeRect, shapeMetrics, borderMetrics, borderColors, gradient ); boxNode->setBoxData( centerNodeRect, shapeMetrics, borderMetrics, borderColors, gradient );
TicksNode* needleNode; TicksNode* needleNode;
if ( boxNode->childCount() == 0 ) if ( boxNode->childCount() == 0 )
{ {
needleNode = new TicksNode( Qt::red ); needleNode = new TicksNode();
} }
else else
{ {
needleNode = static_cast< TicksNode* >( boxNode->childAtIndex( 0 ) ); needleNode = static_cast< TicksNode* >( boxNode->childAtIndex( 0 ) );
} }
QColor color = speedometer->color( Speedometer::Needle );
needleNode->setColor( color );
auto panelRadius = static_cast< float >( panelRect.width() / 2 ); auto panelRadius = static_cast< float >( panelRect.width() / 2 );
auto needleWidth = 2; // ### do differently somehow auto needleWidth = speedometer->metric( Speedometer::Needle | QskAspect::MinimumWidth );
auto needleMargin = speedometer->metric( Speedometer::Needle | QskAspect::Margin );
QRectF needleRect( center.x() - needleWidth , center.y() - needleWidth , QRectF needleRect( center.x() - needleWidth , center.y() - needleWidth ,
panelRadius - ( needleWidth + 10 ), 2 * needleWidth ); panelRadius - ( needleWidth + needleMargin ), 2 * needleWidth );
float xStart = center.x() - needleWidth ; float xStart = center.x();
float yStart = center.y(); float yStart = center.y();
float angle = speedometer->value(); float angle = speedometer->value();
qreal cosine = qCos( qDegreesToRadians( angle ) ); qreal cosine = qCos( qDegreesToRadians( angle ) );
qreal sine = qSin( qDegreesToRadians( angle ) ); qreal sine = qSin( qDegreesToRadians( angle ) );
float needleRadius = panelRadius - 10; // 10 == margins ### skinhint float needleRadius = panelRadius - needleMargin;
float xEnd = center.x() + needleRadius * cosine; float xEnd = center.x() + needleRadius * cosine;
float yEnd = center.y() + needleRadius * sine; float yEnd = center.y() + needleRadius * sine;