diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index f09a2375..0a53e444 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -12,6 +12,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -23,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -98,12 +102,10 @@ namespace return value * factor; } -#if 0 inline double operator ""_dp( long double value ) { return dpToPixels( value ); } -#endif inline double operator ""_dp( unsigned long long int value ) { @@ -221,11 +223,11 @@ void Editor::setupCheckBox() { using Q = QskCheckBox; - setSpacing( Q::Panel, 10_dp ); + setSpacing( Q::Panel, 40_dp ); setStrutSize( Q::Box, 24_dp, 24_dp ); - setPadding( Q::Box, 6_dp ); + setPadding( Q::Box, 4_dp ); setBoxShape( Q::Box, 2_dp ); setBoxBorderMetrics( Q::Box, 2_dp ); setBoxBorderColors( Q::Box, m_pal.onBackground ); @@ -242,6 +244,14 @@ void Editor::setupCheckBox() setColor( Q::Text, m_pal.onBackground ); setTextOptions( Q::Text, Qt::ElideMiddle, QskTextOptions::NoWrap ); + + setStrutSize( Q::Ripple, { 53.33_dp, 53.33_dp } ); + setBoxShape( Q::Ripple, 100, Qt::RelativeSize ); + setGradient( Q::Ripple, Qt::transparent ); + setGradient( Q::Ripple | Q::Hovered | Q::Checked, m_pal.primary8 ); + setGradient( Q::Ripple | Q::Hovered, m_pal.onSurface8 ); + setGradient( Q::Ripple | Q::Hovered | Q::Pressed, m_pal.primary12 ); + setGradient( Q::Ripple | Q::Pressed, m_pal.primary12 ); } void Editor::setupBox() @@ -978,6 +988,7 @@ QskMaterial3Theme::QskMaterial3Theme(Lightness lightness, shadow = m_palettes[ Neutral ].toned( 0 ).rgb(); } + primary8 = QskRgb::toTransparentF( primary, 0.08 ); primary12 = QskRgb::toTransparentF( primary, 0.12 ); surface1 = flattenedColor( primary, background, 0.05 ); @@ -986,6 +997,7 @@ QskMaterial3Theme::QskMaterial3Theme(Lightness lightness, surface4 = flattenedColor( primary, background, 0.12 ); surface5 = flattenedColor( primary, background, 0.14 ); + onSurface8 = QskRgb::toTransparentF( onSurface, 0.08 ); onSurface12 = QskRgb::toTransparentF( onSurface, 0.12 ); onSurface38 = QskRgb::toTransparentF( onSurface, 0.38 ); @@ -996,9 +1008,24 @@ QskMaterial3Theme::QskMaterial3Theme(Lightness lightness, elevationLight3 = QskShadowMetrics( -1, 11, { 0, 2 } ); } +QskMaterial3GraphicProvder::QskMaterial3GraphicProvder( QObject* parent ) + : Inherited( parent ) +{ +} + +const QskGraphic* QskMaterial3GraphicProvder::loadGraphic( const QString& id ) const +{ + const QString name = QString( ":/icons/qvg/%1.qvg" ).arg( id ); + const QskGraphic graphic = QskGraphicIO::read( name ); + + return graphic.isNull() ? nullptr : new QskGraphic( graphic ); +} + QskMaterial3Skin::QskMaterial3Skin( const QskMaterial3Theme& palette, QObject* parent ) : Inherited( parent ) { + addGraphicProvider( {}, new QskMaterial3GraphicProvder() ); + setupFonts(); Editor editor( &hintTable(), palette ); @@ -1009,6 +1036,24 @@ QskMaterial3Skin::~QskMaterial3Skin() { } +QskGraphic QskMaterial3Skin::symbol( int symbolType ) const +{ + switch ( symbolType ) + { + case QskStandardSymbol::CheckMark: + { + const auto* provider = graphicProvider( {} ); + return *( provider->requestGraphic( "check_small" ) ); + } + case QskStandardSymbol::CrossMark: + { + return {}; + } + default: + return Inherited::symbol( symbolType ); + } +} + void QskMaterial3Skin::setupFonts() { Inherited::setupFonts( QStringLiteral( "Roboto" ) ); diff --git a/skins/material3/QskMaterial3Skin.h b/skins/material3/QskMaterial3Skin.h index af04c787..abe37236 100644 --- a/skins/material3/QskMaterial3Skin.h +++ b/skins/material3/QskMaterial3Skin.h @@ -8,6 +8,7 @@ #include "QskMaterial3Global.h" +#include #include #include #include @@ -39,6 +40,7 @@ class QSK_MATERIAL3_EXPORT QskMaterial3Theme QskMaterial3Theme( Lightness, std::array< QskHctColor, NumPaletteTypes > ); QRgb primary; + QRgb primary8; QRgb primary12; QRgb onPrimary; QRgb primaryContainer; @@ -69,6 +71,7 @@ class QSK_MATERIAL3_EXPORT QskMaterial3Theme QRgb surface5; QRgb onSurface; + QRgb onSurface8; QRgb onSurface12; QRgb onSurface38; @@ -92,6 +95,19 @@ class QSK_MATERIAL3_EXPORT QskMaterial3Theme std::array< QskHctColor, NumPaletteTypes > m_palettes; }; +class QSK_MATERIAL3_EXPORT QskMaterial3GraphicProvder : public QskGraphicProvider +{ + Q_OBJECT + + using Inherited = QskGraphicProvider; + + public: + QskMaterial3GraphicProvder( QObject* parent = nullptr ); + + protected: + virtual const QskGraphic* loadGraphic( const QString& id ) const override; +}; + class QSK_MATERIAL3_EXPORT QskMaterial3Skin : public QskSkin { Q_OBJECT @@ -102,6 +118,8 @@ class QSK_MATERIAL3_EXPORT QskMaterial3Skin : public QskSkin QskMaterial3Skin( const QskMaterial3Theme&, QObject* parent = nullptr ); ~QskMaterial3Skin() override; + virtual QskGraphic symbol( int symbolType ) const override; + enum FontRole { M3BodyMedium = QskSkin::HugeFont + 1, diff --git a/skins/material3/icons.qrc b/skins/material3/icons.qrc new file mode 100644 index 00000000..1c012b6a --- /dev/null +++ b/skins/material3/icons.qrc @@ -0,0 +1,5 @@ + + + icons/qvg/check_small.qvg + + diff --git a/skins/material3/icons/check_small.svg b/skins/material3/icons/check_small.svg new file mode 100644 index 00000000..3fce0e84 --- /dev/null +++ b/skins/material3/icons/check_small.svg @@ -0,0 +1,4 @@ + + + + diff --git a/skins/material3/icons/qvg/check_small.qvg b/skins/material3/icons/qvg/check_small.qvg new file mode 100644 index 00000000..19ae6901 Binary files /dev/null and b/skins/material3/icons/qvg/check_small.qvg differ diff --git a/skins/material3/material3.pro b/skins/material3/material3.pro index 97317b2d..fafc9a08 100644 --- a/skins/material3/material3.pro +++ b/skins/material3/material3.pro @@ -16,8 +16,10 @@ SOURCES += \ QskMaterial3Skin.cpp \ QskMaterial3SkinFactory.cpp +RESOURCES += \ + icons.qrc \ + OTHER_FILES += metadata.json target.path = $${QSK_INSTALL_PLUGINS}/$${QSK_PLUGIN_SUBDIR} INSTALLS = target - diff --git a/src/controls/QskCheckBox.cpp b/src/controls/QskCheckBox.cpp index 425772e1..72b2960a 100644 --- a/src/controls/QskCheckBox.cpp +++ b/src/controls/QskCheckBox.cpp @@ -9,6 +9,7 @@ QSK_SUBCONTROL( QskCheckBox, Panel ) QSK_SUBCONTROL( QskCheckBox, Box ) QSK_SUBCONTROL( QskCheckBox, Indicator ) QSK_SUBCONTROL( QskCheckBox, Text ) +QSK_SUBCONTROL( QskCheckBox, Ripple ) class QskCheckBox::PrivateData { diff --git a/src/controls/QskCheckBox.h b/src/controls/QskCheckBox.h index 0f67fd74..cac63fe1 100644 --- a/src/controls/QskCheckBox.h +++ b/src/controls/QskCheckBox.h @@ -17,7 +17,7 @@ class QSK_EXPORT QskCheckBox : public QskAbstractButton using Inherited = QskAbstractButton; public: - QSK_SUBCONTROLS( Panel, Box, Indicator, Text ) + QSK_SUBCONTROLS( Panel, Box, Indicator, Text, Ripple ) QskCheckBox( QQuickItem* parent = nullptr ); QskCheckBox( const QString&, QQuickItem* parent = nullptr ); diff --git a/src/controls/QskCheckBoxSkinlet.cpp b/src/controls/QskCheckBoxSkinlet.cpp index 62d55e0e..0ab03219 100644 --- a/src/controls/QskCheckBoxSkinlet.cpp +++ b/src/controls/QskCheckBoxSkinlet.cpp @@ -15,7 +15,7 @@ QskCheckBoxSkinlet::QskCheckBoxSkinlet( QskSkin* skin ) : QskSkinlet( skin ) { - setNodeRoles( { BoxRole, IndicatorRole, TextRole } ); + setNodeRoles( { BoxRole, IndicatorRole, TextRole, RippleRole } ); } QskCheckBoxSkinlet::~QskCheckBoxSkinlet() @@ -47,6 +47,11 @@ QRectF QskCheckBoxSkinlet::subControlRect( const QskSkinnable* skinnable, return textRect( checkBox, contentsRect ); } + if ( subControl == QskCheckBox::Ripple ) + { + return rippleRect( checkBox, contentsRect ); + } + return contentsRect; } @@ -85,6 +90,21 @@ QRectF QskCheckBoxSkinlet::boxRect( return r; } +QRectF QskCheckBoxSkinlet::rippleRect( + const QskCheckBox* checkBox, const QRectF& rect ) const +{ + const auto rippleSize = checkBox->strutSizeHint( QskCheckBox::Ripple ); + const auto boxSize = checkBox->strutSizeHint( QskCheckBox::Box ); + + const auto w = ( rippleSize.width() - boxSize.width() ) / 2; + const auto h = ( rippleSize.height() - boxSize.height() ) / 2; + + auto r = boxRect( checkBox, rect ); + r = r.marginsAdded( { w, h, w, h } ); + + return r; +} + QSGNode* QskCheckBoxSkinlet::updateSubNode( const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const { @@ -103,6 +123,11 @@ QSGNode* QskCheckBoxSkinlet::updateSubNode( case TextRole: return updateTextNode( checkBox, node ); + + case RippleRole: + { + return updateBoxNode( checkBox, node, QskCheckBox::Ripple ); + } } return Inherited::updateSubNode( skinnable, nodeRole, node ); diff --git a/src/controls/QskCheckBoxSkinlet.h b/src/controls/QskCheckBoxSkinlet.h index aaca18e7..19ddee11 100644 --- a/src/controls/QskCheckBoxSkinlet.h +++ b/src/controls/QskCheckBoxSkinlet.h @@ -23,6 +23,7 @@ class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet BoxRole, IndicatorRole, TextRole, + RippleRole, RoleCount }; @@ -43,6 +44,7 @@ class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet private: QRectF textRect( const QskCheckBox*, const QRectF& ) const; QRectF boxRect( const QskCheckBox*, const QRectF& ) const; + QRectF rippleRect( const QskCheckBox*, const QRectF& ) const; QSGNode* updateIndicatorNode( const QskCheckBox*, QSGNode* ) const; QSGNode* updateTextNode( const QskCheckBox*, QSGNode* ) const;