From 62c5bc5fdc1342664873a279e087fdfe5103b379 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Tue, 11 Jul 2023 09:35:28 +0200 Subject: [PATCH] scroll view: Add Hovered state for the scroll bar --- skins/fluent2/QskFluent2Skin.cpp | 11 ++++++++ skins/material3/QskMaterial3Skin.cpp | 6 ++-- src/controls/QskScrollView.cpp | 38 +++++++++++++++++++++++++ src/controls/QskScrollView.h | 6 ++++ src/controls/QskScrollViewSkinlet.cpp | 40 ++++++++++++++++++++++++--- 5 files changed, 94 insertions(+), 7 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index 2a9f7833..f924283c 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -1095,7 +1095,18 @@ void Editor::setupScrollViewMetrics() using Q = QskScrollView; for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } ) + { setMetric( subControl | A::Size, 2 ); + setMetric( subControl | A::Size | Q::Hovered, 6, + { QskStateCombination::CombinationNoState, Q::Pressed } ); + setAlignment( subControl, Qt::AlignRight ); + } + + for ( auto subControl : { Q::HorizontalScrollHandle, Q::VerticalScrollHandle } ) + { + setBoxShape( subControl, { 100, Qt::RelativeSize }, + { QskStateCombination::CombinationNoState, Q::Hovered | Q::Pressed } ); + } const auto handleExtent = 40.0; setStrutSize( Q::HorizontalScrollHandle, handleExtent, 0.0 ); diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 88c51314..b78f6096 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -1129,7 +1129,7 @@ void Editor::setupScrollView() for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } ) { - setMetric( subControl | A::Size, 10_dp ); + setMetric( subControl | A::Size, 6_dp ); setPadding( subControl, 0 ); } @@ -1139,9 +1139,9 @@ void Editor::setupScrollView() for ( auto subControl : { Q::HorizontalScrollHandle, Q::VerticalScrollHandle } ) { - setBoxShape( subControl, 3_dp ); + setBoxShape( subControl, { 100, Qt::RelativeSize } ); setBoxBorderMetrics( subControl, 0 ); - setGradient( subControl, m_pal.primary ); + setGradient( subControl, m_pal.secondary ); setAnimation( subControl | A::Color, qskDuration ); } diff --git a/src/controls/QskScrollView.cpp b/src/controls/QskScrollView.cpp index 8fd03456..1eb919f9 100644 --- a/src/controls/QskScrollView.cpp +++ b/src/controls/QskScrollView.cpp @@ -62,6 +62,7 @@ QskScrollView::QskScrollView( QQuickItem* parent ) : Inherited( parent ) , m_data( new PrivateData() ) { + setAcceptHoverEvents( true ); } QskScrollView::~QskScrollView() @@ -117,6 +118,17 @@ QskAspect::States QskScrollView::scrollHandleStates( Qt::Orientation orientation if ( m_data->isScrolling == orientation ) states |= Pressed; + const auto subControl = ( orientation == Qt::Horizontal ) ? HorizontalScrollBar : VerticalScrollBar; + + if( effectiveSkinHint( subControl | Hovered ).toBool() ) + { + states |= Hovered; + } + else + { + states &= ~Hovered; + } + return states; } @@ -234,6 +246,21 @@ void QskScrollView::mouseUngrabEvent() m_data->resetScrolling( this ); } +void QskScrollView::hoverEnterEvent( QHoverEvent* event ) +{ + updateHoverHints( event ); +} + +void QskScrollView::hoverMoveEvent( QHoverEvent* event ) +{ + updateHoverHints( event ); +} + +void QskScrollView::hoverLeaveEvent( QHoverEvent* event ) +{ + updateHoverHints( event ); +} + #ifndef QT_NO_WHEELEVENT QPointF QskScrollView::scrollOffset( const QWheelEvent* event ) const @@ -325,4 +352,15 @@ Qt::Orientations QskScrollView::scrollableOrientations() const return orientations; } +void QskScrollView::updateHoverHints( QHoverEvent* event ) +{ + const auto pos = qskHoverPosition( event ); + + const bool hBarHovered = subControlRect( HorizontalScrollBar ).contains( pos ); + setSkinHint( HorizontalScrollBar | Hovered, hBarHovered ); + + const bool yBarHovered = subControlRect( VerticalScrollBar ).contains( pos ); + setSkinHint( VerticalScrollBar | Hovered, yBarHovered ); +} + #include "moc_QskScrollView.cpp" diff --git a/src/controls/QskScrollView.h b/src/controls/QskScrollView.h index fe0dfa38..2c8877e5 100644 --- a/src/controls/QskScrollView.h +++ b/src/controls/QskScrollView.h @@ -54,11 +54,17 @@ class QSK_EXPORT QskScrollView : public QskScrollBox void mouseReleaseEvent( QMouseEvent* ) override; void mouseUngrabEvent() override; + void hoverEnterEvent( QHoverEvent* ) override; + void hoverMoveEvent( QHoverEvent* ) override; + void hoverLeaveEvent( QHoverEvent* ) override; + #ifndef QT_NO_WHEELEVENT QPointF scrollOffset( const QWheelEvent* ) const override; #endif private: + void updateHoverHints( QHoverEvent* ); + class PrivateData; std::unique_ptr< PrivateData > m_data; }; diff --git a/src/controls/QskScrollViewSkinlet.cpp b/src/controls/QskScrollViewSkinlet.cpp index b1f2d7e5..0dc050bc 100644 --- a/src/controls/QskScrollViewSkinlet.cpp +++ b/src/controls/QskScrollViewSkinlet.cpp @@ -252,6 +252,8 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView, QskSkinStateChanger stateChanger( scrollView ); stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); + const auto width = scrollView->metric( Q::VerticalScrollBar | QskAspect::Size ); + const auto padding = scrollView->paddingHint( Q::VerticalScrollBar ); const auto strut = scrollView->strutSizeHint( Q::VerticalScrollHandle ); @@ -262,6 +264,19 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView, qskAlignedHandle( y1, y2, sbRect.height(), strut.height(), top, bottom ); handleRect = sbRect; + handleRect.setWidth( width ); + + const auto alignment = scrollView->alignmentHint( Q::VerticalScrollBar ); + + if( alignment & Qt::AlignHCenter ) + { + handleRect.moveCenter( sbRect.center() ); + } + else if( alignment & Qt::AlignRight ) + { + handleRect.moveRight( sbRect.right() ); + } + handleRect.setTop( sbRect.y() + top ); handleRect.setBottom( sbRect.y() + bottom ); handleRect.adjust( padding.left(), 0, -padding.right(), 0 ); @@ -273,6 +288,8 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView, QskSkinStateChanger stateChanger( scrollView ); stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); + const auto height = scrollView->metric( Q::HorizontalScrollBar | QskAspect::Size ); + const auto padding = scrollView->paddingHint( Q::HorizontalScrollBar ); const qreal x1 = pos.x() / scrollableSize.width(); @@ -284,6 +301,19 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView, qskAlignedHandle( x1, x2, sbRect.width(), strut.width(), left, right ); handleRect = sbRect; + handleRect.setHeight( height ); + + const auto alignment = scrollView->alignmentHint( Q::HorizontalScrollBar ); + + if( alignment & Qt::AlignVCenter ) + { + handleRect.moveCenter( sbRect.center() ); + } + else if( alignment & Qt::AlignBottom ) + { + handleRect.moveBottom( sbRect.bottom() ); + } + handleRect.setLeft( sbRect.x() + left ); handleRect.setRight( sbRect.x() + right ); handleRect.adjust( 0, padding.top(), 0, -padding.bottom() ); @@ -307,25 +337,27 @@ QRectF QskScrollViewSkinlet::scrollBarRect( const QskScrollView* scrollView, QskSkinStateChanger stateChanger( scrollView ); stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); + const auto h = qMax( scrollView->metric( Q::HorizontalScrollBar | A::Size ), + scrollView->metric( Q::HorizontalScrollBar | A::Size | Q::Hovered ) ); + + const qreal w = qMax( scrollView->metric( Q::VerticalScrollBar | A::Size ), + scrollView->metric( Q::VerticalScrollBar | A::Size | Q::Hovered ) ); + if ( orientation == Qt::Horizontal ) { - const qreal h = scrollView->metric( Q::HorizontalScrollBar | A::Size ); r.setTop( r.bottom() - h ); if ( scrollOrientations & Qt::Vertical ) { - const qreal w = scrollView->metric( Q::VerticalScrollBar | A::Size ); r.setRight( r.right() - w ); } } else { - const qreal w = scrollView->metric( Q::VerticalScrollBar | A::Size ); r.setLeft( r.right() - w ); if ( scrollOrientations & Qt::Horizontal ) { - const qreal h = scrollView->metric( Q::HorizontalScrollBar | A::Size ); r.setBottom( r.bottom() - h ); } }