Speedometer: inherit from QskRangeControl and make skinnable (#62)
* Speedometer: Inherit from QskRangeControl We don't need start/endAngle() etc. and value() anymore, but can use the methods from QskRangeControl. * Speedometer: Make it skinnable * automotive example: Only use two specially created skins ... because the default skins do not have hints for e.g. the speedometer. Also, display the speedometer page by default.
This commit is contained in:
parent
6b47678805
commit
60a4f2ff1f
|
@ -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 } )
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include <QDate>
|
||||
#include <QImage>
|
||||
|
||||
#define SPEEDO 0
|
||||
#define SPEEDO 1
|
||||
|
||||
MainWindow::MainWindow()
|
||||
{
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
QStringList SkinFactory::skinNames() const
|
||||
{
|
||||
return { "DefaultSkin", "OtherSkin", "SquiekSkin", "MaterialSkin" };
|
||||
return { "DefaultSkin", "OtherSkin" };
|
||||
}
|
||||
|
||||
QskSkin* SkinFactory::createSkin( const QString& skinName )
|
||||
|
|
|
@ -5,47 +5,14 @@
|
|||
|
||||
QSK_SUBCONTROL( Speedometer, Panel )
|
||||
QSK_SUBCONTROL( Speedometer, Labels )
|
||||
QSK_SUBCONTROL( Speedometer, NeedleHead )
|
||||
QSK_SUBCONTROL( Speedometer, Needle )
|
||||
|
||||
Speedometer::Speedometer( QQuickItem* parent ) :
|
||||
QskControl( parent ),
|
||||
m_value( 0.0 ),
|
||||
m_startAngle( -215 ),
|
||||
m_endAngle( 35 )
|
||||
QskRangeControl( parent )
|
||||
{
|
||||
}
|
||||
|
||||
float Speedometer::value() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
void Speedometer::setValue( float value )
|
||||
{
|
||||
m_value = value;
|
||||
update();
|
||||
}
|
||||
|
||||
float Speedometer::startAngle() const
|
||||
{
|
||||
return m_startAngle;
|
||||
}
|
||||
|
||||
void Speedometer::setStartAngle( float startAngle )
|
||||
{
|
||||
m_startAngle = startAngle;
|
||||
}
|
||||
|
||||
float Speedometer::endAngle() const
|
||||
{
|
||||
return m_endAngle;
|
||||
}
|
||||
|
||||
void Speedometer::setEndAngle( float endAngle )
|
||||
{
|
||||
m_endAngle = endAngle;
|
||||
}
|
||||
|
||||
QVector< QString > Speedometer::labels() const
|
||||
{
|
||||
return m_labels;
|
||||
|
|
|
@ -1,33 +1,21 @@
|
|||
#ifndef SPEEDOMETER_H
|
||||
#define SPEEDOMETER_H
|
||||
|
||||
#include <QskControl.h>
|
||||
#include <QskRangeControl.h>
|
||||
|
||||
class Speedometer : public QskControl
|
||||
class Speedometer : public QskRangeControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Panel, Labels, Needle )
|
||||
QSK_SUBCONTROLS( Panel, Labels, NeedleHead, Needle )
|
||||
|
||||
Speedometer( QQuickItem* parent = nullptr );
|
||||
|
||||
float value() const;
|
||||
void setValue( float value ); // angle; should be within a set range
|
||||
|
||||
float startAngle() const;
|
||||
void setStartAngle( float startAngle );
|
||||
|
||||
float endAngle() const;
|
||||
void setEndAngle( float endAngle );
|
||||
|
||||
QVector< QString > labels() const;
|
||||
void setLabels( const QVector< QString >& labels );
|
||||
|
||||
private:
|
||||
float m_value;
|
||||
float m_startAngle;
|
||||
float m_endAngle;
|
||||
float m_labelsStep;
|
||||
QVector< QString > m_labels;
|
||||
};
|
||||
|
|
|
@ -29,11 +29,12 @@ SpeedometerDisplay::SpeedometerDisplay( QQuickItem *parent ) :
|
|||
m_box->setSpacing( 20 );
|
||||
|
||||
m_revCounter->setObjectName( QStringLiteral( "RevCounter" ) );
|
||||
int startAngle = 145, endAngle = 305, value = 200, numberLabels = 8;
|
||||
m_revCounter->setStartAngle( startAngle );
|
||||
m_revCounter->setEndAngle( endAngle );
|
||||
m_revCounter->setValue( value );
|
||||
m_revCounter->setMinimum( 145 );
|
||||
m_revCounter->setMaximum( 305 );
|
||||
m_revCounter->setValue( 200 );
|
||||
QVector< QString > revCounterLabels;
|
||||
int numberLabels = 8;
|
||||
revCounterLabels.reserve( numberLabels );
|
||||
|
||||
for ( int i = 0; i < numberLabels; ++i )
|
||||
{
|
||||
|
@ -43,14 +44,11 @@ SpeedometerDisplay::SpeedometerDisplay( QQuickItem *parent ) :
|
|||
m_revCounter->setLabels( revCounterLabels );
|
||||
|
||||
m_speedometer->setObjectName( QStringLiteral( "Speedometer" ) );
|
||||
value = 280;
|
||||
numberLabels = 23;
|
||||
startAngle = -215;
|
||||
endAngle = 35;
|
||||
m_speedometer->setStartAngle( startAngle );
|
||||
m_speedometer->setEndAngle( endAngle );
|
||||
m_speedometer->setValue( value );
|
||||
m_speedometer->setMinimum( -215 );
|
||||
m_speedometer->setMaximum( 35 );
|
||||
m_speedometer->setValue( -90 );
|
||||
QVector< QString > speedometerLabels;
|
||||
numberLabels = 23;
|
||||
speedometerLabels.reserve( numberLabels );
|
||||
|
||||
for ( int i = 0; i < numberLabels; ++i )
|
||||
|
@ -76,8 +74,8 @@ SpeedometerDisplay::SpeedometerDisplay( QQuickItem *parent ) :
|
|||
|
||||
|
||||
m_fuelGauge->setObjectName( QStringLiteral( "Fuel Gauge" ) );
|
||||
m_fuelGauge->setStartAngle( 195 );
|
||||
m_fuelGauge->setEndAngle( 345 );
|
||||
m_fuelGauge->setMinimum( 195 );
|
||||
m_fuelGauge->setMaximum( 345 );
|
||||
m_fuelGauge->setValue( 330 );
|
||||
|
||||
QVector< QString > fuelGaugeLabels;
|
||||
|
|
|
@ -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,11 +111,14 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode( const Speedometer* speedometer, Q
|
|||
|
||||
if ( ticksNode == nullptr )
|
||||
{
|
||||
ticksNode = new TicksNode( Qt::white );
|
||||
ticksNode = new TicksNode();
|
||||
}
|
||||
|
||||
const float startAngle = speedometer->startAngle();
|
||||
const float endAngle = speedometer->endAngle();
|
||||
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 );
|
||||
|
||||
auto geometry = ticksNode->geometry();
|
||||
|
@ -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 ) );
|
||||
|
||||
float 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
|
||||
for( int i = 0; i < labelsCount; ++i, angle += step )
|
||||
|
@ -141,33 +148,30 @@ QSGNode* SpeedometerSkinlet::updateLabelsNode( const Speedometer* speedometer, Q
|
|||
qreal cosine = qCos( qDegreesToRadians( angle ) );
|
||||
qreal sine = qSin( qDegreesToRadians( angle ) );
|
||||
|
||||
float xStart = center.x() + radius * cosine;
|
||||
float yStart = center.y() + radius * sine;
|
||||
auto xStart = center.x() + radius * cosine;
|
||||
auto yStart = center.y() + radius * sine;
|
||||
|
||||
// ### skin hint for each of highlighted / normal marks
|
||||
qreal length = 15;
|
||||
float xEnd = center.x() + ( radius - length ) * cosine;
|
||||
float yEnd = center.y() + ( radius - length ) * sine;
|
||||
auto xEnd = center.x() + ( radius - length ) * cosine;
|
||||
auto yEnd = center.y() + ( radius - length ) * sine;
|
||||
|
||||
vertexData[0].set( xStart, yStart );
|
||||
vertexData[1].set( xEnd, yEnd );
|
||||
|
||||
vertexData += 2;
|
||||
|
||||
QVector< QString > labels = speedometer->labels();
|
||||
|
||||
// only create a text node if there is a label for it:
|
||||
if ( labels.count() > i )
|
||||
{
|
||||
const QString& text = labels.at( i );
|
||||
|
||||
float w = fontMetrics.width( text );
|
||||
float h = fontMetrics.height();
|
||||
float adjustX = ( -0.5 * cosine - 0.5 ) * w;
|
||||
float adjustY = ( -0.5 * sine - 0.5 ) * h;
|
||||
auto w = fontMetrics.width( text );
|
||||
auto h = fontMetrics.height();
|
||||
auto adjustX = ( -0.5 * cosine - 0.5 ) * w;
|
||||
auto adjustY = ( -0.5 * sine - 0.5 ) * h;
|
||||
|
||||
float numbersX = xEnd + ( -1 * numbersMargins.left() * cosine ) + adjustX;
|
||||
float numbersY = yEnd + ( -1 * numbersMargins.top() * sine ) + adjustY;
|
||||
auto numbersX = xEnd + ( -1 * numbersMargins.left() * cosine ) + adjustX;
|
||||
auto numbersY = yEnd + ( -1 * numbersMargins.top() * sine ) + adjustY;
|
||||
|
||||
QRectF numbersRect( numbersX, numbersY, w, h );
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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,
|
||||
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 );
|
||||
|
||||
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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue