Material is using the term "Ripple" for 2 different type of effects - Flutter

calls them "Splash" and "Highlight". We are using Splash too.
This commit is contained in:
Uwe Rathmann 2023-03-01 10:51:46 +01:00
parent 5a25804cec
commit 28432446e6
9 changed files with 91 additions and 98 deletions

View File

@ -666,7 +666,7 @@ void Editor::setupPushButton()
setShadowColor( Q::Panel, m_pal.shadow );
setAnimation( Q::Ripple | QskAspect::Color, qskDuration );
setAnimation( Q::Splash | QskAspect::Color, qskDuration );
// elevated buttons:
@ -675,7 +675,8 @@ void Editor::setupPushButton()
setShadowMetrics( Q::Panel | M3::Elevated, m_pal.elevation1 );
setColor( Q::Text | M3::Elevated, m_pal.primary );
setGraphicRole( Q::Graphic | M3::Elevated, QskMaterial3Skin::GraphicRolePrimary );
setGradient( Q::Ripple | M3::Elevated, stateLayerColor( m_pal.primary, m_pal.pressedOpacity ) );
setGradient( Q::Splash | M3::Elevated,
stateLayerColor( m_pal.primary, m_pal.pressedOpacity ) );
setGradient( Q::Panel | M3::Elevated | Q::Disabled, m_pal.onSurface12 );
setShadowMetrics( Q::Panel | M3::Elevated | Q::Disabled, m_pal.elevation0 );
@ -712,7 +713,7 @@ void Editor::setupPushButton()
setGradient( Q::Panel | Q::Pressed, focusColor );
setGradient( Q::Ripple, stateLayerColor( m_pal.onPrimary, m_pal.hoverOpacity ) );
setGradient( Q::Splash, stateLayerColor( m_pal.onPrimary, m_pal.hoverOpacity ) );
setColor( Q::Text, m_pal.onPrimary );
setColor( Q::Text | Q::Disabled, m_pal.onSurface38 );
@ -727,7 +728,7 @@ void Editor::setupPushButton()
setShadowMetrics( Q::Panel | M3::Tonal, m_pal.elevation0 );
setColor( Q::Text | M3::Tonal, m_pal.onSecondaryContainer );
setGraphicRole( Q::Graphic | M3::Tonal, QskMaterial3Skin::GraphicRoleOnSecondaryContainer );
setGradient( Q::Ripple | M3::Tonal,
setGradient( Q::Splash | M3::Tonal,
stateLayerColor( m_pal.onSecondaryContainer, m_pal.pressedOpacity ) );
setGradient( Q::Panel | M3::Tonal | Q::Disabled, m_pal.onSurface12 );
@ -755,9 +756,11 @@ void Editor::setupPushButton()
setBoxBorderColors( Q::Panel | M3::Outlined, m_pal.outline );
setBoxBorderMetrics( Q::Panel | M3::Outlined, 1_dp );
setShadowMetrics( Q::Panel | M3::Outlined, m_pal.elevation0 );
setColor( Q::Text | M3::Outlined, m_pal.primary );
setGraphicRole( Q::Graphic | M3::Outlined, QskMaterial3Skin::GraphicRolePrimary );
setGradient( Q::Ripple | M3::Outlined, stateLayerColor( m_pal.outline, m_pal.pressedOpacity ) );
setGradient( Q::Splash | M3::Outlined,
stateLayerColor( m_pal.outline, m_pal.pressedOpacity ) );
setBoxBorderColors( Q::Panel | M3::Outlined | Q::Disabled, m_pal.onSurface12 );
setColor( Q::Text | M3::Outlined | Q::Disabled, m_pal.onSurface38 );
@ -772,11 +775,13 @@ void Editor::setupPushButton()
setGradient( Q::Panel | M3::Outlined | Q::Pressed, m_pal.primary12 );
// text buttons:
/*
text buttons:
// trick: Use a transparent color that changes between skins;
// otherwise we would fall back to the filled button color
// during skin change:
trick: Use a transparent color that changes between skins;
otherwise we would fall back to the filled button color
during skin change:
*/
QColor c( m_pal.background );
c.setAlpha( 255 );
setGradient( Q::Panel | M3::Text, c );
@ -784,7 +789,8 @@ void Editor::setupPushButton()
setShadowMetrics( Q::Panel | M3::Text, m_pal.elevation0 );
setColor( Q::Text | M3::Text, m_pal.primary );
setGraphicRole( Q::Graphic | M3::Text, QskMaterial3Skin::GraphicRolePrimary );
setGradient( Q::Ripple | M3::Text, stateLayerColor( m_pal.primary, m_pal.pressedOpacity ) );
setGradient( Q::Splash | M3::Text,
stateLayerColor( m_pal.primary, m_pal.pressedOpacity ) );
setColor( Q::Text | M3::Text | Q::Disabled, m_pal.onSurface38 );
setGraphicRole( Q::Graphic | M3::Text | Q::Disabled, QskMaterial3Skin::GraphicRoleOnSurface38 );

View File

@ -15,7 +15,7 @@ QSK_SUBCONTROL( QskComboBox, Panel )
QSK_SUBCONTROL( QskComboBox, Graphic )
QSK_SUBCONTROL( QskComboBox, Text )
QSK_SUBCONTROL( QskComboBox, OpenMenuGraphic )
QSK_SUBCONTROL( QskComboBox, Ripple )
QSK_SUBCONTROL( QskComboBox, Splash )
QSK_SYSTEM_STATE( QskComboBox, Pressed, QskAspect::FirstSystemState << 1 )
QSK_SYSTEM_STATE( QskComboBox, PopupOpen, QskAspect::FirstSystemState << 2 )

View File

@ -22,7 +22,7 @@ class QSK_EXPORT QskComboBox : public QskControl
using Inherited = QskControl;
public:
QSK_SUBCONTROLS( Panel, Graphic, Text, OpenMenuGraphic, Ripple )
QSK_SUBCONTROLS( Panel, Graphic, Text, OpenMenuGraphic, Splash )
QSK_STATES( Pressed, PopupOpen )
QskComboBox( QQuickItem* parent = nullptr );
@ -61,7 +61,7 @@ class QSK_EXPORT QskComboBox : public QskControl
virtual void closePopup();
void click();
void setCurrentIndex( int index );
void setCurrentIndex( int );
Q_SIGNALS:
void currentIndexChanged( int );

View File

@ -67,7 +67,7 @@ namespace
QskComboBoxSkinlet::QskComboBoxSkinlet( QskSkin* skin )
: Inherited( skin )
{
setNodeRoles( { PanelRole, GraphicRole, TextRole, OpenMenuGraphicRole, RippleRole } );
setNodeRoles( { PanelRole, SplashRole, GraphicRole, TextRole, OpenMenuGraphicRole } );
}
QskComboBoxSkinlet::~QskComboBoxSkinlet() = default;
@ -79,6 +79,12 @@ QRectF QskComboBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
const auto* box = static_cast< const QskComboBox* >( skinnable );
if ( subControl == Q::Panel )
return contentsRect;
if ( subControl == Q::Splash )
return splashRect( box, contentsRect );
if ( subControl == Q::Text || subControl == Q::Graphic )
{
const auto r = box->subControlContentsRect( contentsRect, Q::Panel );
@ -97,16 +103,6 @@ QRectF QskComboBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
return rect;
}
if ( subControl == Q::Panel )
{
return contentsRect;
}
if ( subControl == Q::Ripple )
{
return rippleRect( box, contentsRect );
}
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
@ -115,54 +111,56 @@ QSGNode* QskComboBoxSkinlet::updateSubNode(
{
using Q = QskComboBox;
const auto bar = static_cast< const QskComboBox* >( skinnable );
const auto box = static_cast< const QskComboBox* >( skinnable );
switch ( nodeRole )
{
case PanelRole:
{
return updateBoxNode( bar, node, Q::Panel );
return updateBoxNode( box, node, Q::Panel );
}
case GraphicRole:
{
return updateGraphicNode( bar, node, bar->graphic(), Q::Graphic );
return updateGraphicNode( box, node, box->graphic(), Q::Graphic );
}
case TextRole:
{
return updateTextNode( bar, node );
return updateTextNode( box, node );
}
case OpenMenuGraphicRole:
{
const auto symbol = bar->isPopupOpen() ? QskStandardSymbol::ComboBoxSymbolPopupOpen
const auto symbol = box->isPopupOpen()
? QskStandardSymbol::ComboBoxSymbolPopupOpen
: QskStandardSymbol::ComboBoxSymbolPopupClosed;
const auto graphic = bar->effectiveSkin()->symbol( symbol );
return updateGraphicNode( bar, node, graphic, Q::OpenMenuGraphic );
const auto graphic = box->effectiveSkin()->symbol( symbol );
return updateGraphicNode( box, node, graphic, Q::OpenMenuGraphic );
}
}
return Inherited::updateSubNode( skinnable, nodeRole, node );
}
QRectF QskComboBoxSkinlet::rippleRect(
const QskComboBox* bar, const QRectF& contentsRect ) const
QRectF QskComboBoxSkinlet::splashRect(
const QskComboBox* box, const QRectF& contentsRect ) const
{
using Q = QskComboBox;
QRectF rect;
const auto ratio = bar->metric( Q::Ripple | QskAspect::Size );
const auto ratio = box->metric( Q::Splash | QskAspect::Size );
if ( ratio > 0.0 )
{
const auto pos = bar->effectiveSkinHint(
Q::Ripple | QskAspect::Metric | QskAspect::Position ).toPointF();
rect = subControlRect( box, contentsRect, Q::Panel );
const auto panelRect = subControlRect( bar, contentsRect, Q::Panel );
const auto pos = box->positionHint( Q::Splash );
const qreal w = 2.0 * rect.width() * ratio;
rect.setSize( 2.0 * panelRect.size() * ratio );
rect.moveCenter( pos );
rect.setX( pos - 0.5 * w );
rect.setWidth( w );
}
return rect;
@ -185,27 +183,27 @@ QSGNode* QskComboBoxSkinlet::updateTextNode(
alignment, box->text(), Q::Text );
}
QSGNode* QskComboBoxSkinlet::updateRippleNode(
const QskComboBox* button, QSGNode* node ) const
QSGNode* QskComboBoxSkinlet::updateSplashNode(
const QskComboBox* box, QSGNode* node ) const
{
using Q = QskComboBox;
const auto rippleRect = button->subControlRect( Q::Ripple );
if ( rippleRect.isEmpty() )
const auto splashRect = box->subControlRect( Q::Splash );
if ( splashRect.isEmpty() )
return nullptr;
auto clipNode = updateBoxClipNode( button, node,
button->subControlRect( Q::Panel ), Q::Panel );
auto clipNode = updateBoxClipNode( box, node,
box->subControlRect( Q::Panel ), Q::Panel );
if ( clipNode )
{
auto boxNode = QskSGNode::findChildNode( clipNode, RippleRole );
boxNode = updateBoxNode( button, boxNode, rippleRect, Q::Ripple );
auto boxNode = QskSGNode::findChildNode( clipNode, SplashRole );
boxNode = updateBoxNode( box, boxNode, splashRect, Q::Splash );
if ( boxNode == nullptr )
return nullptr;
QskSGNode::setNodeRole( boxNode, RippleRole );
QskSGNode::setNodeRole( boxNode, SplashRole );
if ( boxNode->parent() != clipNode )
clipNode->appendChildNode( boxNode );
}

View File

@ -23,7 +23,7 @@ class QSK_EXPORT QskComboBoxSkinlet : public QskSkinlet
GraphicRole,
TextRole,
OpenMenuGraphicRole,
RippleRole,
SplashRole,
RoleCount
};
@ -42,10 +42,10 @@ class QSK_EXPORT QskComboBoxSkinlet : public QskSkinlet
quint8 nodeRole, QSGNode* ) const override;
private:
QRectF rippleRect( const QskComboBox*, const QRectF& ) const;
QRectF splashRect( const QskComboBox*, const QRectF& ) const;
QSGNode* updateTextNode( const QskComboBox*, QSGNode* ) const;
QSGNode* updateRippleNode( const QskComboBox*, QSGNode* ) const;
QSGNode* updateSplashNode( const QskComboBox*, QSGNode* ) const;
};
#endif

View File

@ -13,9 +13,10 @@
#include "QskSkin.h"
#include "QskSkinlet.h"
#include "QskTextOptions.h"
#include "QskEvent.h"
QSK_SUBCONTROL( QskPushButton, Panel )
QSK_SUBCONTROL( QskPushButton, Ripple )
QSK_SUBCONTROL( QskPushButton, Splash )
QSK_SUBCONTROL( QskPushButton, Text )
QSK_SUBCONTROL( QskPushButton, Graphic )
@ -304,11 +305,11 @@ void QskPushButton::mousePressEvent( QMouseEvent* event )
using A = QskAspect;
const auto hint = animationHint( Ripple | A::Color );
const auto hint = animationHint( Splash | A::Color );
if( hint.isValid() )
{
setSkinHint( Ripple | A::Metric | A::Position, event->pos() );
startTransition( Ripple | A::Metric | A::Size, hint, 0.0, 1.0 );
setPositionHint( Splash, qskMousePosition( event ).x() );
startTransition( Splash | A::Metric | A::Size, hint, 0.0, 1.0 );
}
}

View File

@ -45,7 +45,7 @@ class QSK_EXPORT QskPushButton : public QskAbstractButton
using Inherited = QskAbstractButton;
public:
QSK_SUBCONTROLS( Panel, Ripple, Text, Graphic )
QSK_SUBCONTROLS( Panel, Splash, Text, Graphic )
enum Emphasis
{

View File

@ -56,7 +56,7 @@ namespace
QskPushButtonSkinlet::QskPushButtonSkinlet( QskSkin* skin )
: Inherited( skin )
{
setNodeRoles( { PanelRole, RippleRole, GraphicRole, TextRole } );
setNodeRoles( { PanelRole, SplashRole, GraphicRole, TextRole } );
}
QskPushButtonSkinlet::~QskPushButtonSkinlet() = default;
@ -68,6 +68,12 @@ QRectF QskPushButtonSkinlet::subControlRect( const QskSkinnable* skinnable,
const auto button = static_cast< const QskPushButton* >( skinnable );
if ( subControl == Q::Panel )
return contentsRect;
if ( subControl == Q::Splash )
return splashRect( button, contentsRect );
if ( ( subControl == Q::Text ) || ( subControl == Q::Graphic ) )
{
const auto r = button->subControlContentsRect( contentsRect, Q::Panel );
@ -78,16 +84,6 @@ QRectF QskPushButtonSkinlet::subControlRect( const QskSkinnable* skinnable,
return layoutEngine.subControlRect( subControl );
}
if ( subControl == Q::Panel )
{
return contentsRect;
}
if ( subControl == Q::Ripple )
{
return rippleRect( button, contentsRect );
}
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
@ -101,46 +97,38 @@ QSGNode* QskPushButtonSkinlet::updateSubNode(
switch ( nodeRole )
{
case PanelRole:
{
return updateBoxNode( button, node, Q::Panel );
}
case RippleRole:
{
return updateRippleNode( button, node );
}
case SplashRole:
return updateSplashNode( button, node );
case TextRole:
{
return updateTextNode( button, node );
}
case GraphicRole:
{
return updateGraphicNode( button, node, button->graphic(), Q::Graphic );
}
}
return Inherited::updateSubNode( skinnable, nodeRole, node );
}
QRectF QskPushButtonSkinlet::rippleRect(
QRectF QskPushButtonSkinlet::splashRect(
const QskPushButton* button, const QRectF& contentsRect ) const
{
using Q = QskPushButton;
QRectF rect;
const auto ratio = button->metric( Q::Ripple | QskAspect::Size );
const auto ratio = button->metric( Q::Splash | QskAspect::Size );
if ( ratio > 0.0 )
{
const auto pos = button->effectiveSkinHint(
Q::Ripple | QskAspect::Metric | QskAspect::Position ).toPointF();
rect = subControlRect( button, contentsRect, Q::Panel );
const auto panelRect = subControlRect( button, contentsRect, Q::Panel );
const auto pos = button->positionHint( Q::Splash );
const qreal w = 2.0 * rect.width() * ratio;
rect.setSize( { 2.0 * panelRect.width() * ratio, panelRect.height() * 2.0 } );
rect.moveCenter( pos );
rect.setX( pos - 0.5 * w );
rect.setWidth( w );
}
return rect;
@ -163,13 +151,13 @@ QSGNode* QskPushButtonSkinlet::updateTextNode(
alignment, button->text(), Q::Text );
}
QSGNode* QskPushButtonSkinlet::updateRippleNode(
QSGNode* QskPushButtonSkinlet::updateSplashNode(
const QskPushButton* button, QSGNode* node ) const
{
using Q = QskPushButton;
const auto rippleRect = button->subControlRect( Q::Ripple );
if ( rippleRect.isEmpty() )
const auto splashRect = button->subControlRect( Q::Splash );
if ( splashRect.isEmpty() )
return nullptr;
auto clipNode = updateBoxClipNode( button, node,
@ -177,13 +165,13 @@ QSGNode* QskPushButtonSkinlet::updateRippleNode(
if ( clipNode )
{
auto boxNode = QskSGNode::findChildNode( clipNode, RippleRole );
boxNode = updateBoxNode( button, boxNode, rippleRect, Q::Ripple );
auto boxNode = QskSGNode::findChildNode( clipNode, SplashRole );
boxNode = updateBoxNode( button, boxNode, splashRect, Q::Splash );
if ( boxNode == nullptr )
return nullptr;
QskSGNode::setNodeRole( boxNode, RippleRole );
QskSGNode::setNodeRole( boxNode, SplashRole );
if ( boxNode->parent() != clipNode )
clipNode->appendChildNode( boxNode );
}

View File

@ -20,7 +20,7 @@ class QSK_EXPORT QskPushButtonSkinlet : public QskSkinlet
enum NodeRole
{
PanelRole,
RippleRole,
SplashRole,
TextRole,
GraphicRole,
@ -41,10 +41,10 @@ class QSK_EXPORT QskPushButtonSkinlet : public QskSkinlet
quint8 nodeRole, QSGNode* ) const override;
private:
QRectF rippleRect( const QskPushButton*, const QRectF& ) const;
QRectF splashRect( const QskPushButton*, const QRectF& ) const;
QSGNode* updateTextNode( const QskPushButton*, QSGNode* ) const;
QSGNode* updateRippleNode( const QskPushButton*, QSGNode* ) const;
QSGNode* updateSplashNode( const QskPushButton*, QSGNode* ) const;
};
#endif