From f126a9007d3787d4758de1c950e531dd12ef0aa2 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Fri, 30 Jun 2023 15:28:20 +0200 Subject: [PATCH] menu: Support hovered state --- skins/fluent2/QskFluent2Skin.cpp | 4 +++- skins/material3/QskMaterial3Skin.cpp | 11 ++++++++--- src/controls/QskMenu.cpp | 26 ++++++++++++++++++++++++++ src/controls/QskMenu.h | 5 +++++ src/controls/QskMenuSkinlet.cpp | 12 ++++++++++++ 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index 0cd05f89..fdb93bf1 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -724,6 +724,8 @@ void Editor::setupMenuColors( setGradient( Q::Panel, pal.background.flyout.defaultColor ); setShadowColor( Q::Panel, theme.shadow.flyout.color ); + setGradient( Q::Segment | Q::Hovered, pal.fillColor.subtle.secondary ); + setGradient( Q::Segment | Q::Selected, pal.fillColor.subtle.secondary ); /* @@ -734,7 +736,7 @@ void Editor::setupMenuColors( const auto c1 = pal.fillColor.subtle.secondary; const auto c2 = pal.fillColor.accent.defaultColor; - setBoxBorderColors( Q::Segment | Q::Selected, + setBoxBorderColors( Q::Segment | Q::Selected, QskGradient( { { 0.25, c1 }, { 0.25, c2 }, { 0.75, c2 }, { 0.75, c1 } } ) ); setColor( Q::Text, pal.fillColor.text.primary ); diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 21665588..8728a0ee 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -340,8 +340,8 @@ void Editor::setupMenu() // The color here is primary with an opacity of 8% - we blend that // with the background, because we don't want the menu to have transparency: - const auto panel = flattenedColor( m_pal.primary, m_pal.background, 0.08 ); - setGradient( Q::Panel, panel ); + const auto panelColor = flattenedColor( m_pal.primary, m_pal.background, 0.08 ); + setGradient( Q::Panel, panelColor ); setShadowMetrics( Q::Panel, m_pal.elevation2 ); setShadowColor( Q::Panel, m_pal.shadow ); @@ -355,7 +355,12 @@ void Editor::setupMenu() setSpacing( Q::Segment, 5_dp ); setGradient( Q::Segment, Qt::transparent ); - setGradient( Q::Cursor, m_pal.primary12 ); + const auto hoverColor = flattenedColor( m_pal.onSurface, panelColor, m_pal.hoverOpacity ); + setGradient( Q::Segment | Q::Hovered, hoverColor ); + + setGradient( Q::Segment | Q::Selected, m_pal.primary12 ); + const auto hoverSelectedColor = flattenedColor( m_pal.onSurface, m_pal.primary12, m_pal.hoverOpacity ); + setGradient( Q::Segment | Q::Selected | Q::Hovered, hoverSelectedColor ); setPadding( Q::Icon, 7_dp ); setStrutSize( Q::Icon, 24_dp, 24_dp ); diff --git a/src/controls/QskMenu.cpp b/src/controls/QskMenu.cpp index 3e2c2cba..b72877e8 100644 --- a/src/controls/QskMenu.cpp +++ b/src/controls/QskMenu.cpp @@ -72,6 +72,8 @@ QskMenu::QskMenu( QQuickItem* parent ) connect( this, &QskMenu::opened, this, [this]() { m_data->triggeredIndex = -1; } ); + + setAcceptHoverEvents( true ); } QskMenu::~QskMenu() @@ -319,6 +321,30 @@ void QskMenu::keyReleaseEvent( QKeyEvent* ) } } +void QskMenu::hoverEnterEvent( QHoverEvent* event ) +{ + using A = QskAspect; + + setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) ); + update(); +} + +void QskMenu::hoverMoveEvent( QHoverEvent* event ) +{ + using A = QskAspect; + + setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) ); + update(); +} + +void QskMenu::hoverLeaveEvent( QHoverEvent* ) +{ + using A = QskAspect; + + setSkinHint( Segment | Hovered | A::Metric | A::Position, QPointF() ); + update(); +} + #ifndef QT_NO_WHEELEVENT void QskMenu::wheelEvent( QWheelEvent* event ) diff --git a/src/controls/QskMenu.h b/src/controls/QskMenu.h index 9a4e6624..ce4da4fc 100644 --- a/src/controls/QskMenu.h +++ b/src/controls/QskMenu.h @@ -68,6 +68,7 @@ class QSK_EXPORT QskMenu : public QskPopup QVector< int > actions() const; int currentIndex() const; + QString currentText() const; int triggeredIndex() const; @@ -97,6 +98,10 @@ class QSK_EXPORT QskMenu : public QskPopup void keyPressEvent( QKeyEvent* ) override; void keyReleaseEvent( QKeyEvent* ) override; + void hoverEnterEvent( QHoverEvent* ) override; + void hoverMoveEvent( QHoverEvent* ) override; + void hoverLeaveEvent( QHoverEvent* ) override; + #ifndef QT_NO_WHEELEVENT void wheelEvent( QWheelEvent* ) override; #endif diff --git a/src/controls/QskMenuSkinlet.cpp b/src/controls/QskMenuSkinlet.cpp index b5e9b8e3..c99e94e1 100644 --- a/src/controls/QskMenuSkinlet.cpp +++ b/src/controls/QskMenuSkinlet.cpp @@ -385,6 +385,7 @@ QskAspect::States QskMenuSkinlet::sampleStates( const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index ) const { using Q = QskMenu; + using A = QskAspect; auto states = Inherited::sampleStates( skinnable, subControl, index ); @@ -394,6 +395,17 @@ QskAspect::States QskMenuSkinlet::sampleStates( if ( menu->currentIndex() == menu->actions()[ index ] ) states |= QskMenu::Selected; + + const auto cursorPos = menu->effectiveSkinHint( Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF(); + + if( !cursorPos.isNull() && menu->indexAtPosition( cursorPos ) == index ) + { + states |= Q::Hovered; + } + else + { + states &= ~Q::Hovered; + } } return states;