Support more than one data point in a diagram
This commit is contained in:
parent
d4bc4e12f5
commit
ad03c0f6a0
|
@ -9,17 +9,21 @@ class Diagram::PrivateData
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<QPointF> dataPoints;
|
QVector<QVector<QPointF> > dataPoints;
|
||||||
int xGridLines = -1;
|
int xGridLines = -1;
|
||||||
qreal yMax = -1;
|
qreal yMax = -1;
|
||||||
Qsk::Position position = Qsk::Bottom;
|
Qsk::Position position = Qsk::Bottom;
|
||||||
Types types = Area;
|
QVector<Types> types;
|
||||||
};
|
};
|
||||||
|
|
||||||
QSK_SUBCONTROL( Diagram, Chart )
|
QSK_SUBCONTROL( Diagram, Chart )
|
||||||
QSK_SUBCONTROL( Diagram, Segments )
|
QSK_SUBCONTROL( Diagram, Segments )
|
||||||
QSK_SUBCONTROL( Diagram, ChartLine )
|
QSK_SUBCONTROL( Diagram, ChartLine1 )
|
||||||
QSK_SUBCONTROL( Diagram, ChartArea )
|
QSK_SUBCONTROL( Diagram, ChartArea1 )
|
||||||
|
QSK_SUBCONTROL( Diagram, ChartLine2 )
|
||||||
|
QSK_SUBCONTROL( Diagram, ChartArea2 )
|
||||||
|
QSK_SUBCONTROL( Diagram, ChartLine3 )
|
||||||
|
QSK_SUBCONTROL( Diagram, ChartArea3 )
|
||||||
|
|
||||||
Diagram::Diagram( QQuickItem* parent )
|
Diagram::Diagram( QQuickItem* parent )
|
||||||
: Inherited( parent )
|
: Inherited( parent )
|
||||||
|
@ -31,24 +35,20 @@ Diagram::~Diagram()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<QPointF> Diagram::dataPoints() const
|
QVector< QVector<QPointF> > Diagram::dataPoints() const
|
||||||
{
|
{
|
||||||
return m_data->dataPoints;
|
return m_data->dataPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Diagram::setDataPoints( const QVector<QPointF>& dataPoints )
|
void Diagram::addDataPoints( const QVector<QPointF>& dataPoints, const Types& types )
|
||||||
{
|
{
|
||||||
m_data->dataPoints = dataPoints;
|
m_data->dataPoints.append( dataPoints );
|
||||||
|
m_data->types.append( types );
|
||||||
}
|
}
|
||||||
|
|
||||||
Diagram::Types Diagram::types() const
|
Diagram::Types Diagram::typesAt( uint pos ) const
|
||||||
{
|
{
|
||||||
return m_data->types;
|
return m_data->types.at( pos );
|
||||||
}
|
|
||||||
|
|
||||||
void Diagram::setTypes( Types types )
|
|
||||||
{
|
|
||||||
m_data->types = types;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal Diagram::yMax() const
|
qreal Diagram::yMax() const
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Diagram : public QskControl
|
||||||
using Inherited = QskControl;
|
using Inherited = QskControl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QSK_SUBCONTROLS( Chart, Segments, ChartLine, ChartArea )
|
QSK_SUBCONTROLS( Chart, Segments, ChartLine1, ChartArea1, ChartLine2, ChartArea2, ChartLine3, ChartArea3 )
|
||||||
|
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
|
@ -25,11 +25,10 @@ class Diagram : public QskControl
|
||||||
Diagram( QQuickItem* parent = nullptr );
|
Diagram( QQuickItem* parent = nullptr );
|
||||||
~Diagram() override;
|
~Diagram() override;
|
||||||
|
|
||||||
QVector<QPointF> dataPoints() const;
|
QVector< QVector<QPointF> > dataPoints() const;
|
||||||
void setDataPoints( const QVector<QPointF>& dataPoints );
|
void addDataPoints( const QVector<QPointF>& dataPoints, const Types& types );
|
||||||
|
|
||||||
Types types() const;
|
Types typesAt( uint pos ) const;
|
||||||
void setTypes( Types types );
|
|
||||||
|
|
||||||
qreal yMax() const;
|
qreal yMax() const;
|
||||||
void setYMax( qreal yMax );
|
void setYMax( qreal yMax );
|
||||||
|
|
|
@ -3,6 +3,39 @@
|
||||||
#include "nodes/DiagramDataNode.h"
|
#include "nodes/DiagramDataNode.h"
|
||||||
#include "nodes/DiagramSegmentsNode.h"
|
#include "nodes/DiagramSegmentsNode.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
QskAspect::Subcontrol areaForIndex( int i )
|
||||||
|
{
|
||||||
|
switch( i )
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return Diagram::ChartArea2;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
return Diagram::ChartArea3;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return Diagram::ChartArea1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QskAspect::Subcontrol lineForIndex( int i )
|
||||||
|
{
|
||||||
|
switch( i )
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return Diagram::ChartLine2;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
return Diagram::ChartLine3;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return Diagram::ChartLine1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DiagramSkinlet::DiagramSkinlet( QskSkin* skin )
|
DiagramSkinlet::DiagramSkinlet( QskSkin* skin )
|
||||||
: QskSkinlet( skin )
|
: QskSkinlet( skin )
|
||||||
{
|
{
|
||||||
|
@ -46,59 +79,78 @@ QSGNode* DiagramSkinlet::updateSubNode(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGNode* DiagramSkinlet::updateChartNode( const Diagram* distribution, QSGNode* node ) const
|
QSGNode* DiagramSkinlet::updateChartNode( const Diagram* diagram, QSGNode* node ) const
|
||||||
{
|
{
|
||||||
if( node == nullptr )
|
if( node == nullptr )
|
||||||
{
|
{
|
||||||
node = new IdlChartNode;
|
node = new IdlChartNode; // ### rename
|
||||||
}
|
}
|
||||||
|
|
||||||
using Q = Diagram;
|
using Q = Diagram;
|
||||||
const QRectF rect = distribution->subControlRect( Q::Chart );
|
const QRectF rect = diagram->subControlRect( Q::Chart );
|
||||||
const QVector<QPointF> dataPoints = distribution->dataPoints();
|
const qreal yMax = diagram->yMax();
|
||||||
const qreal yMax = distribution->yMax();
|
const Qsk::Position position = diagram->chartPosition();
|
||||||
const Qsk::Position position = distribution->chartPosition();
|
|
||||||
int lineWidth = distribution->metric( Diagram::ChartLine | QskAspect::Size );
|
|
||||||
QVector<Diagram::Type> types = {Diagram::Line, Diagram::Area};
|
QVector<Diagram::Type> types = {Diagram::Line, Diagram::Area};
|
||||||
|
|
||||||
int nodeIndex = 0;
|
for( int i = 0; i < diagram->dataPoints().size(); ++i )
|
||||||
|
{
|
||||||
|
QSGNode* chartNode;
|
||||||
|
|
||||||
for( int i = 0; i < types.size(); ++i )
|
if( node->childCount() > i )
|
||||||
{
|
{
|
||||||
if( distribution->types() & types.at( i ) )
|
chartNode = node->childAtIndex( i );
|
||||||
{
|
|
||||||
IdlChartNode* lineNode;
|
|
||||||
|
|
||||||
if( node->childCount() > nodeIndex )
|
|
||||||
{
|
|
||||||
lineNode = static_cast<IdlChartNode*>( node->childAtIndex( nodeIndex ) );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lineNode = new IdlChartNode;
|
chartNode = new QSGNode;
|
||||||
node->appendChildNode( lineNode );
|
node->appendChildNode( chartNode );
|
||||||
}
|
}
|
||||||
|
|
||||||
const IdlChartNode::Type nodeType = ( types.at( i ) == Diagram::Line ) ? IdlChartNode::Line : IdlChartNode::Area;
|
const QVector<QPointF> dataPoints = diagram->dataPoints().at( i );
|
||||||
const QColor color = ( types.at( i ) == Diagram::Line ) ? distribution->color( Q::ChartLine )
|
int nodeIndex = 0;
|
||||||
: distribution->color( Q::ChartArea );
|
QskAspect::Subcontrol lineSubcontrol = lineForIndex( i );
|
||||||
|
QskAspect::Subcontrol areaSubcontrol = areaForIndex( i );
|
||||||
|
int lineWidth = diagram->metric( lineSubcontrol | QskAspect::Size );
|
||||||
|
|
||||||
lineNode->update( rect, nodeType, color, dataPoints, yMax, position, lineWidth );
|
for( int j = 0; j < types.size(); ++j )
|
||||||
|
{
|
||||||
|
if( diagram->typesAt( i ) & types.at( j ) )
|
||||||
|
{
|
||||||
|
IdlChartNode* dataPointNode;
|
||||||
|
|
||||||
|
if( chartNode->childCount() > nodeIndex )
|
||||||
|
{
|
||||||
|
dataPointNode = static_cast<IdlChartNode*>( chartNode->childAtIndex( nodeIndex ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataPointNode = new IdlChartNode;
|
||||||
|
chartNode->appendChildNode( dataPointNode );
|
||||||
|
}
|
||||||
|
|
||||||
|
const IdlChartNode::Type nodeType = ( types.at( j ) == Diagram::Line ) ? IdlChartNode::Line : IdlChartNode::Area;
|
||||||
|
const QColor color = ( types.at( j ) == Diagram::Line ) ? diagram->color( lineSubcontrol )
|
||||||
|
: diagram->color( areaSubcontrol );
|
||||||
|
|
||||||
|
dataPointNode->update( rect, nodeType, color, dataPoints, yMax, position, lineWidth );
|
||||||
nodeIndex++;
|
nodeIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while( nodeIndex < node->childCount() )
|
while( nodeIndex < chartNode->childCount() )
|
||||||
{
|
{
|
||||||
node->removeChildNode( node->childAtIndex( nodeIndex++ ) );
|
chartNode->removeChildNode( chartNode->childAtIndex( nodeIndex++ ) );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ### also check for superfluous nodes here
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGNode* DiagramSkinlet::updateSeparatorNode( const Diagram* discharge, QSGNode* node ) const
|
QSGNode* DiagramSkinlet::updateSeparatorNode( const Diagram* diagram, QSGNode* node ) const
|
||||||
{
|
{
|
||||||
const int xGridLines = discharge->xGridLines();
|
const int xGridLines = diagram->xGridLines();
|
||||||
|
|
||||||
if( xGridLines <= 0 )
|
if( xGridLines <= 0 )
|
||||||
{
|
{
|
||||||
|
@ -113,9 +165,9 @@ QSGNode* DiagramSkinlet::updateSeparatorNode( const Diagram* discharge, QSGNode*
|
||||||
}
|
}
|
||||||
|
|
||||||
using Q = Diagram;
|
using Q = Diagram;
|
||||||
const QRectF rect = discharge->subControlRect( Q::Chart );
|
const QRectF rect = diagram->subControlRect( Q::Chart );
|
||||||
const QColor color = discharge->color( Q::Segments );
|
const QColor color = diagram->color( Q::Segments );
|
||||||
const QVector<QPointF> dataPoints = discharge->dataPoints();
|
const QVector< QVector<QPointF> > dataPoints = diagram->dataPoints();
|
||||||
|
|
||||||
separatorNode->update( rect, color, dataPoints, xGridLines );
|
separatorNode->update( rect, color, dataPoints, xGridLines );
|
||||||
|
|
||||||
|
|
|
@ -156,8 +156,9 @@ void Skin::initHints( const Palette& palette )
|
||||||
|
|
||||||
|
|
||||||
// new diagram:
|
// new diagram:
|
||||||
ed.setMetric( Diagram::ChartLine | QskAspect::Size, 2 );
|
ed.setColor( Diagram::ChartArea1, "#886776ff" );
|
||||||
ed.setColor( Diagram::ChartArea, "#886776ff" );
|
ed.setColor( Diagram::ChartArea2, "#88ff3122" );
|
||||||
|
ed.setColor( Diagram::ChartArea3, "#88ff7d34" );
|
||||||
|
|
||||||
|
|
||||||
// light intensity:
|
// light intensity:
|
||||||
|
@ -178,7 +179,6 @@ void Skin::initHints( const Palette& palette )
|
||||||
ed.setGradient( RoundButton::Panel, palette.roundButton );
|
ed.setGradient( RoundButton::Panel, palette.roundButton );
|
||||||
ed.setBoxBorderColors( WeekdayBox::Panel, palette.weekdayBox );
|
ed.setBoxBorderColors( WeekdayBox::Panel, palette.weekdayBox );
|
||||||
ed.setColor( QskTextLabel::Text, palette.text );
|
ed.setColor( QskTextLabel::Text, palette.text );
|
||||||
ed.setColor( Diagram::ChartLine, Qt::transparent );
|
|
||||||
ed.setColor( WeekdayLabel::Text, palette.text );
|
ed.setColor( WeekdayLabel::Text, palette.text );
|
||||||
ed.setColor( ShadowPositioner::Panel, palette.shadow );
|
ed.setColor( ShadowPositioner::Panel, palette.shadow );
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,23 +70,33 @@ UsageDiagram::UsageDiagram( QQuickItem* parent )
|
||||||
setAutoAddChildren( false );
|
setAutoAddChildren( false );
|
||||||
setAutoLayoutChildren( true );
|
setAutoLayoutChildren( true );
|
||||||
|
|
||||||
m_diagram->setTypes( Diagram::Line | Diagram::Area );
|
|
||||||
m_diagram->setChartPosition( Qsk::Bottom );
|
|
||||||
int number = 100;
|
int number = 100;
|
||||||
QVector<QPointF> dataPoints1;
|
std::vector< std::vector<qreal> > yValues =
|
||||||
dataPoints1.reserve( number );
|
{
|
||||||
std::vector<qreal> yValues1 = {40, 20, 30, 50, 30, 70, 80, 100, 90, 60};
|
{40, 20, 30, 50, 30, 70, 80, 100, 90, 60},
|
||||||
qreal t0 = yValues1[0];
|
{15, 70, 40, 60, 10, 90, 20, 40, 45, 50},
|
||||||
|
{70, 40, 60, 10, 70, 20, 50, 20, 30, 40}
|
||||||
|
};
|
||||||
|
|
||||||
|
for( int i = 0; i < 3; ++i )
|
||||||
|
{
|
||||||
|
auto y = yValues.at( i );
|
||||||
|
|
||||||
|
QVector<QPointF> dataPoints;
|
||||||
|
dataPoints.reserve( number );
|
||||||
|
qreal t0 = y[0];
|
||||||
qreal step = 10;
|
qreal step = 10;
|
||||||
boost::math::cubic_b_spline<qreal> spline1( yValues1.data(), yValues1.size(), t0, step );
|
boost::math::cubic_b_spline<qreal> spline( y.data(), y.size(), t0, step );
|
||||||
|
|
||||||
for( int x = 0; x < number; ++x )
|
for( int x = 0; x < number; ++x )
|
||||||
{
|
{
|
||||||
qreal y = spline1( x );
|
const qreal y = spline( x );
|
||||||
dataPoints1.append( QPointF( x, y ) );
|
dataPoints.append( QPointF( x, y ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_diagram->addDataPoints( dataPoints, Diagram::Area );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_diagram->setDataPoints( dataPoints1 );
|
|
||||||
m_diagram->setYMax( 100 );
|
m_diagram->setYMax( 100 );
|
||||||
addItem( m_diagram );
|
addItem( m_diagram );
|
||||||
|
|
||||||
|
@ -113,4 +123,11 @@ UsageDiagram::UsageDiagram( QQuickItem* parent )
|
||||||
m_captionBox->addItem( new CaptionItem( CaptionItem::Gas, this ) );
|
m_captionBox->addItem( new CaptionItem( CaptionItem::Gas, this ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UsageDiagram::updateLayout()
|
||||||
|
{
|
||||||
|
auto weekdaysHeight = m_weekdays->preferredSize().height();
|
||||||
|
m_diagram->setHeight( m_diagram->height() - weekdaysHeight );
|
||||||
|
m_captionBox->setPosition( {0, 0} );
|
||||||
|
}
|
||||||
|
|
||||||
#include "Diagram.moc"
|
#include "Diagram.moc"
|
||||||
|
|
|
@ -130,6 +130,8 @@ class UsageDiagram : public Box
|
||||||
|
|
||||||
UsageDiagram( QQuickItem* parent );
|
UsageDiagram( QQuickItem* parent );
|
||||||
|
|
||||||
|
void updateLayout() override;
|
||||||
|
|
||||||
QskAspect::Subcontrol effectiveSubcontrol(
|
QskAspect::Subcontrol effectiveSubcontrol(
|
||||||
QskAspect::Subcontrol subControl ) const override final
|
QskAspect::Subcontrol subControl ) const override final
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,7 +11,7 @@ IdlChartSegmentsNode::IdlChartSegmentsNode()
|
||||||
setMaterial( &m_material );
|
setMaterial( &m_material );
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdlChartSegmentsNode::update( const QRectF& rect, const QColor& color, const QVector<QPointF>& dataPoints, int xGridLines )
|
void IdlChartSegmentsNode::update( const QRectF& rect, const QColor& color, const QVector<QVector<QPointF> >& dataPoints, int xGridLines )
|
||||||
{
|
{
|
||||||
Q_UNUSED( rect );
|
Q_UNUSED( rect );
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ class IdlChartSegmentsNode : public QSGGeometryNode
|
||||||
public:
|
public:
|
||||||
IdlChartSegmentsNode();
|
IdlChartSegmentsNode();
|
||||||
|
|
||||||
void update( const QRectF& rect, const QColor& color, const QVector<QPointF>& dataPoints, int xGridLines );
|
void update( const QRectF& rect, const QColor& color, const QVector< QVector<QPointF> >& dataPoints, int xGridLines );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSGFlatColorMaterial m_material;
|
QSGFlatColorMaterial m_material;
|
||||||
|
@ -17,6 +17,6 @@ class IdlChartSegmentsNode : public QSGGeometryNode
|
||||||
|
|
||||||
QRectF m_rect;
|
QRectF m_rect;
|
||||||
QColor m_color;
|
QColor m_color;
|
||||||
QVector<QPointF> m_dataPoints;
|
QVector< QVector<QPointF> > m_dataPoints;
|
||||||
int m_xGridLines;
|
int m_xGridLines;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue