diff --git a/skins/material/QskMaterialSkin.cpp b/skins/material/QskMaterialSkin.cpp index ec55b47b..e48e5907 100644 --- a/skins/material/QskMaterialSkin.cpp +++ b/skins/material/QskMaterialSkin.cpp @@ -135,20 +135,23 @@ void Editor::setupControl() void Editor::setupCheckBox() { + using A = QskAspect; using Q = QskCheckBox; - const qreal radius = qskDpiScaled( 18 ); + const qreal size = qskDpiScaled( 18 ); - setMargin( QskCheckBox::Tick, QMarginsF( 3, 5, 3, 3 ) ); - setStrutSize( Q::Box, radius, radius ); + setStrutSize( Q::Panel, size, size ); + setPadding( Q::Panel, 3 ); - setBoxShape( Q::Box, 2 ); + setBoxShape( Q::Panel, 2 ); - setColor( Q::Box, m_pal.secondaryNoSaturation); - setColor( Q::Box | Q::Checked, m_pal.secondary ); - setGradient( Q::Box | Q::Checked | Q::Disabled, QskRgb::Grey ); + setGradient( Q::Panel, m_pal.secondaryNoSaturation ); + setGradient( Q::Panel | Q::Checked, m_pal.secondary ); + setGradient( Q::Panel | Q::Checked | Q::Disabled, QskRgb::Grey ); - setColor( Q::Tick, m_pal.primary ); + setColor( Q::Indicator, m_pal.primary ); + + setAnimation( Q::Panel | A::Color, qskDuration ); } void Editor::setupBox() diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index 09ea727e..035ddb31 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -297,19 +297,24 @@ void Editor::setupBox() void Editor::setupCheckBox() { + using A = QskAspect; using Q = QskCheckBox; const qreal size = qskDpiScaled( 26 ); - setMargin( Q::Tick, QskMargins( qskDpiScaled( 5 ) ) ); + setStrutSize( Q::Panel, size, size ); - setStrutSize( Q::Box, QSizeF( size, size ) ); - setBoxShape( Q::Box, qskDpiScaled( 3 ) ); - setBoxBorderMetrics( Q::Box, qskDpiScaled( 1 ) ); - setBoxBorderColors( Q::Box, m_pal.darker125 ); - setColor( Q::Box, m_pal.lighter135 ); - setColor( Q::Box | Q::Checked, m_pal.highlighted ); - setColor( Q::Tick, m_pal.lighter135 ); + setPadding( Q::Panel, qskDpiScaled( 5 ) ); + setBoxShape( Q::Panel, qskDpiScaled( 3 ) ); + setBoxBorderMetrics( Q::Panel, qskDpiScaled( 1 ) ); + + setBoxBorderColors( Q::Panel, m_pal.darker125 ); + setGradient( Q::Panel, m_pal.lighter135 ); + setGradient( Q::Panel | Q::Checked, m_pal.highlighted ); + + setColor( Q::Indicator, m_pal.lighter135 ); + + setAnimation( Q::Panel | A::Color, qskDuration ); } void Editor::setupPopup() diff --git a/src/controls/QskCheckBox.cpp b/src/controls/QskCheckBox.cpp index 5a5cdbee..69cdb7bd 100644 --- a/src/controls/QskCheckBox.cpp +++ b/src/controls/QskCheckBox.cpp @@ -8,8 +8,8 @@ #include -QSK_SUBCONTROL( QskCheckBox, Box ) -QSK_SUBCONTROL( QskCheckBox, Tick ) +QSK_SUBCONTROL( QskCheckBox, Panel ) +QSK_SUBCONTROL( QskCheckBox, Indicator ) QSK_SYSTEM_STATE( QskCheckBox, PartiallyChecked, QskAspect::LastUserState << 2 ) @@ -28,7 +28,7 @@ class QskCheckBox::PrivateData int groupItemsChecked = 0; - int checkState : 2; + Qt::CheckState checkState : 2; bool checkStateChanging : 1; bool toggleChanging : 1; bool tristate : 1; @@ -57,7 +57,7 @@ bool QskCheckBox::isCheckable() const Qt::CheckState QskCheckBox::checkState() const { - return static_cast< Qt::CheckState >( m_data->checkState ); + return m_data->checkState; } void QskCheckBox::setCheckStateInternal( Qt::CheckState checkState ) @@ -162,8 +162,7 @@ void QskCheckBox::addToGroup( QskCheckBox* groupItem ) connect( groupItem, &QskAbstractButton::toggled, this, [ this, groupItem ]( bool toggled ) { - auto& groupItemsChecked = m_data->groupItemsChecked; - groupItemsChecked += toggled ? 1 : -1; + m_data->groupItemsChecked += toggled ? 1 : -1; updated(); } ); diff --git a/src/controls/QskCheckBox.h b/src/controls/QskCheckBox.h index b1443c1d..9a2fb36e 100644 --- a/src/controls/QskCheckBox.h +++ b/src/controls/QskCheckBox.h @@ -21,7 +21,7 @@ class QSK_EXPORT QskCheckBox : public QskAbstractButton using Inherited = QskAbstractButton; public: - QSK_SUBCONTROLS( Box, Tick ) + QSK_SUBCONTROLS( Panel, Indicator ) QSK_STATES( PartiallyChecked ) QskCheckBox( QQuickItem* parent = nullptr ); 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