diff --git a/examples/iot-dashboard/Card.cpp b/examples/iot-dashboard/Card.cpp index 98f2970c..4d336ebc 100644 --- a/examples/iot-dashboard/Card.cpp +++ b/examples/iot-dashboard/Card.cpp @@ -7,6 +7,6 @@ Card::Card(const QString &title, QskControl *content, QQuickItem *parent ) : Qsk { m_label = new QskTextLabel( m_title, this ); m_content = content; - m_content->setParentItem( this ); + m_content->setParentItem( this ); // ### maybe do it differently m_content->setParent( this ); } diff --git a/examples/iot-dashboard/MainContent.cpp b/examples/iot-dashboard/MainContent.cpp index 0edc1d7a..a7bc3a4a 100644 --- a/examples/iot-dashboard/MainContent.cpp +++ b/examples/iot-dashboard/MainContent.cpp @@ -1,6 +1,7 @@ #include "MainContent.h" #include "Card.h" +#include "PieChart.h" #include @@ -14,7 +15,9 @@ MainContent::MainContent( QQuickItem *parent ) : QskLinearBox( Qt::Horizontal, p m_columns.append( column ); } - auto* pieChart = new QskTextLabel( "here pie chart" ); + auto* pieChart = new PieChart; + QVector< float > angles = { 60, 90, 150, 60 }; + pieChart->setAngles( angles ); addCard( "Sample usage", pieChart, 0 ); auto* barGraph = new QskTextLabel( "here bar graph" ); diff --git a/examples/iot-dashboard/PieChart.cpp b/examples/iot-dashboard/PieChart.cpp new file mode 100644 index 00000000..82dac3bb --- /dev/null +++ b/examples/iot-dashboard/PieChart.cpp @@ -0,0 +1,28 @@ +#include "PieChart.h" + +QSK_SUBCONTROL( PieChart, Panel ) +QSK_SUBCONTROL( PieChart, Labels ) + +PieChart::PieChart( QQuickItem *parent ) : QskControl( parent ) +{ +} + +QVector< float > PieChart::angles() const +{ + return m_angles; +} + +void PieChart::setAngles( const QVector< float >& angles ) +{ + m_angles = angles; +} + +QVector< QString > PieChart::labels() const +{ + return m_labels; +} + +void PieChart::setLabels( const QVector< QString >& labels ) +{ + m_labels = labels; +} diff --git a/examples/iot-dashboard/PieChart.h b/examples/iot-dashboard/PieChart.h new file mode 100644 index 00000000..c23014e5 --- /dev/null +++ b/examples/iot-dashboard/PieChart.h @@ -0,0 +1,26 @@ +#ifndef PIECHART_H +#define PIECHART_H + +#include + +class PieChart : public QskControl +{ + Q_OBJECT + +public: + QSK_SUBCONTROLS( Panel, Labels ) + + PieChart( QQuickItem* parent = nullptr ); + + QVector< float > angles() const; + void setAngles( const QVector< float >& angles ); + + QVector< QString > labels() const; + void setLabels( const QVector< QString >& labels ); + +private: + QVector< float > m_angles; + QVector< QString > m_labels; +}; + +#endif // PIECHART_H diff --git a/examples/iot-dashboard/PieChartSkinlet.cpp b/examples/iot-dashboard/PieChartSkinlet.cpp new file mode 100644 index 00000000..77e9a8f4 --- /dev/null +++ b/examples/iot-dashboard/PieChartSkinlet.cpp @@ -0,0 +1,69 @@ +#include "PieChartSkinlet.h" +#include "PieChart.h" + +#include +#include +#include +#include + +PieChartSkinlet::PieChartSkinlet( QskSkin* skin ) : QskSkinlet( skin ) +{ + setNodeRoles( { PanelRole, LabelsRole } ); +} + +QRectF PieChartSkinlet::subControlRect( const QskSkinnable*, const QRectF& contentsRect, QskAspect::Subcontrol ) const +{ + return contentsRect; +} + +QSGNode* PieChartSkinlet::updateSubNode( const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const +{ + const auto pieChart = static_cast< const PieChart* >( skinnable ); + + switch ( nodeRole ) + { + case PanelRole: + return updatePanelNode( pieChart, node ); + + case LabelsRole: + return updateLabelsNode( pieChart, node ); + + default: + return nullptr; + } +} + +QSGNode* PieChartSkinlet::updatePanelNode( const PieChart* pieChart, QSGNode* node ) const +{ + auto boxNode = static_cast< QskBoxNode* >( node ); + + if ( boxNode == nullptr ) + { + boxNode = new QskBoxNode; + } + + const auto panelRect = subControlRect( pieChart, pieChart->contentsRect(), PieChart::Panel ); + + const qreal radius = panelRect.width() / 2; + + QskBoxShapeMetrics shapeMetrics( radius, radius, radius, radius ); + QskBoxBorderMetrics borderMetrics = pieChart->boxBorderMetricsHint( PieChart::Panel ); + QskBoxBorderColors borderColors = pieChart->boxBorderColorsHint( PieChart::Panel ); + QskGradient gradient = pieChart->gradientHint( PieChart::Panel ); + boxNode->setBoxData( panelRect, shapeMetrics, borderMetrics, borderColors, gradient ); + + return boxNode; +} + +QSGNode* PieChartSkinlet::updateLabelsNode( const PieChart* pieChart, QSGNode* node ) const +{ + const int labelsCount = pieChart->labels().count(); + + // ### actually, we could draw labels with only one entry + if ( labelsCount <= 1 ) + { + return nullptr; + } + + return nullptr; +} diff --git a/examples/iot-dashboard/PieChartSkinlet.h b/examples/iot-dashboard/PieChartSkinlet.h new file mode 100644 index 00000000..53a8ecbf --- /dev/null +++ b/examples/iot-dashboard/PieChartSkinlet.h @@ -0,0 +1,31 @@ +#ifndef PIECHARTSKINLET_H +#define PIECHARTSKINLET_H + +#include + +class PieChart; + +class PieChartSkinlet : public QskSkinlet +{ + Q_GADGET + +public: + enum NodeRole + { + PanelRole, + LabelsRole + }; + + Q_INVOKABLE PieChartSkinlet( QskSkin* skin = nullptr ); + + QRectF subControlRect( const QskSkinnable*, const QRectF&, QskAspect::Subcontrol ) const override; + +protected: + virtual QSGNode* updateSubNode( const QskSkinnable*, quint8 nodeRole, QSGNode* node ) const override; + +private: + QSGNode* updatePanelNode( const PieChart*, QSGNode* ) const; + QSGNode* updateLabelsNode( const PieChart*, QSGNode* ) const; +}; + +#endif // PIECHARTSKINLET_H diff --git a/examples/iot-dashboard/iot-dashboard.pro b/examples/iot-dashboard/iot-dashboard.pro index 473a98a7..0a02d7d2 100644 --- a/examples/iot-dashboard/iot-dashboard.pro +++ b/examples/iot-dashboard/iot-dashboard.pro @@ -4,6 +4,8 @@ SOURCES += \ Card.cpp \ MainContent.cpp \ MenuBar.cpp \ + PieChart.cpp \ + PieChartSkinlet.cpp \ main.cpp \ MainWindow.cpp @@ -11,7 +13,9 @@ HEADERS += \ Card.h \ MainContent.h \ MainWindow.h \ - MenuBar.h + MenuBar.h \ + PieChart.h \ + PieChartSkinlet.h RESOURCES += \ images.qrc