diff --git a/src/controls/QskCheckBoxSkinlet.cpp b/src/controls/QskCheckBoxSkinlet.cpp index e4547658..10fa4421 100644 --- a/src/controls/QskCheckBoxSkinlet.cpp +++ b/src/controls/QskCheckBoxSkinlet.cpp @@ -5,132 +5,129 @@ #include "QskCheckBoxSkinlet.h" #include "QskCheckBox.h" +#include "QskSGNode.h" #include #include namespace { - class Tick : public QSGGeometryNode + class IndicatorNode : public QSGGeometryNode { public: - Tick() - : geometry( QSGGeometry::defaultAttributes_Point2D(), 3 ) + IndicatorNode() + : m_geometry( QSGGeometry::defaultAttributes_Point2D(), 3 ) { - geometry.setDrawingMode( QSGGeometry::DrawLineStrip ); - geometry.setLineWidth( 2 ); - setGeometry( &geometry ); + m_geometry.setDrawingMode( QSGGeometry::DrawLineStrip ); + m_geometry.setLineWidth( 2 ); + setGeometry( &m_geometry ); - setMaterial( &material ); + setMaterial( &m_material ); } - void setColor( const QColor& color ) + void update( bool isPartially, const QRectF& rect, const QColor& color ) { - material.setColor( color ); - markDirty( QSGNode::DirtyMaterial ); - } + if ( color != m_material.color() ) + { + m_material.setColor( color ); + markDirty( QSGNode::DirtyMaterial ); + } - void makeTick( const QRectF& rect ) - { - const auto x = rect.x(); - const auto y = rect.y(); + if ( rect != m_rect || isPartially != m_isPartially ) + { + m_rect = rect; + m_isPartially = isPartially; - auto vertexData = geometry.vertexDataAsPoint2D(); + const auto x = rect.x(); + const auto y = rect.y(); + const auto w = rect.width(); + const auto h = rect.height(); - vertexData[0].set( x, y + rect.height() / 2 ); - vertexData[1].set( x + rect.width() / 3, y + rect.height() ); - vertexData[2].set( x + rect.width(), y ); + auto points = m_geometry.vertexDataAsPoint2D(); - markDirty( QSGNode::DirtyGeometry ); - } - - void makePartially( const QRectF& rect ) - { - const auto x = rect.x(); - const auto y = rect.y(); - - auto vertexData = geometry.vertexDataAsPoint2D(); - - vertexData[0].set( x, y + rect.height() / 2 ); - vertexData[1].set( x, y + rect.height() / 2 ); - vertexData[2].set( x + rect.width(), y + rect.height() / 2 ); - - markDirty( QSGNode::DirtyGeometry ); + if ( isPartially ) + { + points[0].set( x, y + h / 2 ); + points[1] = points[0]; + points[2].set( x + w, y + h / 2 ); + } + else + { + points[0].set( x, y + h / 2 ); + points[1].set( x + w / 3, y + h ); + points[2].set( x + w, y ); + } + + markDirty( QSGNode::DirtyGeometry ); + } } private: - QSGFlatColorMaterial material; - QSGGeometry geometry; + QSGFlatColorMaterial m_material; + QSGGeometry m_geometry; + + QRectF m_rect; + bool m_isPartially; }; } QskCheckBoxSkinlet::QskCheckBoxSkinlet( QskSkin* skin ) : QskSkinlet( skin ) { - setNodeRoles( { BoxRole, TickRole } ); + setNodeRoles( { PanelRole, IndicatorRole } ); } QskCheckBoxSkinlet::~QskCheckBoxSkinlet() { } -QRectF QskCheckBoxSkinlet::subControlRect( - const QskSkinnable*, const QRectF& contentsRect, QskAspect::Subcontrol ) const +QRectF QskCheckBoxSkinlet::subControlRect( const QskSkinnable* skinnable, + const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const { + if ( subControl == QskCheckBox::Indicator ) + return skinnable->innerBox( QskCheckBox::Panel, contentsRect ); + return contentsRect; } QSGNode* QskCheckBoxSkinlet::updateSubNode( const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const { + auto checkBox = static_cast< const QskCheckBox* >( skinnable ); + switch( nodeRole ) { - case BoxRole: - { - return updateBoxNode( skinnable, node, QskCheckBox::Box ); - } + case PanelRole: + return updateBoxNode( skinnable, node, QskCheckBox::Panel ); - case TickRole: - { - auto checkBox = static_cast< const QskCheckBox* >( skinnable ); - return updateTickNode( checkBox, node ); - } + case IndicatorRole: + return updateIndicatorNode( checkBox, node ); } return Inherited::updateSubNode( skinnable, nodeRole, node ); } -QSGNode* QskCheckBoxSkinlet::updateTickNode( +QSGNode* QskCheckBoxSkinlet::updateIndicatorNode( const QskCheckBox* checkBox, QSGNode* node ) const { using Q = QskCheckBox; - if ( checkBox->checkState() == Qt::Unchecked ) + const auto state = checkBox->checkState(); + if ( state == Qt::Unchecked ) return nullptr; - auto rect = checkBox->subControlRect( Q::Tick ); - rect = rect.marginsRemoved( checkBox->marginHint( Q::Tick ) ); + const auto rect = checkBox->subControlRect( Q::Indicator ); + if ( rect.isEmpty() ) + return nullptr; - auto tick = static_cast< Tick* >( node ); - if ( tick == nullptr ) - tick = new Tick(); + auto indicatorNode = QskSGNode::ensureNode< IndicatorNode >( node ); + indicatorNode->update( state != Qt::Checked, rect, checkBox->color( Q::Indicator ) ); - if ( checkBox->checkState() == Qt::PartiallyChecked ) - { - tick->setColor( checkBox->color( Q::Tick | Q::PartiallyChecked ) ); - tick->makePartially( rect ); - } - else - { - tick->setColor( checkBox->color( Q::Tick | Q::Checked ) ); - tick->makeTick( rect ); - } - - return tick; + return indicatorNode; } QSizeF QskCheckBoxSkinlet::sizeHint( const QskSkinnable* skinnable, Qt::SizeHint, const QSizeF& ) const { - return skinnable->strutSizeHint( QskCheckBox::Box ); + return skinnable->strutSizeHint( QskCheckBox::Panel ); } diff --git a/src/controls/QskCheckBoxSkinlet.h b/src/controls/QskCheckBoxSkinlet.h index d703600c..094c5807 100644 --- a/src/controls/QskCheckBoxSkinlet.h +++ b/src/controls/QskCheckBoxSkinlet.h @@ -19,8 +19,8 @@ class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet public: enum NodeRole { - BoxRole, - TickRole, + PanelRole, + IndicatorRole, }; Q_INVOKABLE QskCheckBoxSkinlet( QskSkin* = nullptr ); @@ -36,8 +36,8 @@ class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet QSGNode* updateSubNode( const QskSkinnable*, quint8 nodeRole, QSGNode* ) const override; - private: - QSGNode* updateTickNode( const QskCheckBox*, QSGNode* ) const; + protected: + virtual QSGNode* updateIndicatorNode( const QskCheckBox*, QSGNode* ) const; }; #endif