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;
}
}
} // namespace
DefaultSkin::DefaultSkin( const QString& name, QObject* parent ):
QskSkin( parent ),
@ -101,7 +101,8 @@ void DefaultSkin::initHints()
setColor( QskTextLabel::Text, m_palette->color4 );
// - sound control
// -- sound control
setGradient( SoundControl::Overlay, 0 );
setGradient( SoundControl::CrossHair, m_palette->color3 );
setGradient( SoundControl::Marker, m_palette->color5 );
@ -146,6 +147,30 @@ void DefaultSkin::initHints()
setBoxShape( QskSlider::Handle, 100.0, Qt::RelativeSize );
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
for ( auto state : { QskAspect::NoState, QskSlider::Pressed } )
{

View File

@ -140,6 +140,29 @@ void OtherSkin::initHints()
setBoxBorderMetrics( QskSlider::Handle, 0 );
setBoxShape( QskSlider::Handle, 6 );
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()

View File

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

View File

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

View File

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