diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index 1f99d354..18fc6fe6 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -1023,19 +1023,14 @@ void Editor::setupScrollView() const qreal bw = 1.0; setButton( subControl, Raised, bw ); + setButton( subControl | Q::Pressed, Sunken, bw ); const auto extent = 40_dp; if ( subControl == Q::HorizontalScrollHandle ) - { setStrutSize( subControl, extent, 0.0 ); - setButton( subControl | Q::HorizontalHandlePressed, Sunken, bw ); - } else - { setStrutSize( subControl, 0.0, extent ); - setButton( subControl | Q::VerticalHandlePressed, Sunken, bw ); - } setAnimation( subControl | A::Color, qskDuration ); } diff --git a/src/controls/QskScrollView.cpp b/src/controls/QskScrollView.cpp index a61be872..8fd03456 100644 --- a/src/controls/QskScrollView.cpp +++ b/src/controls/QskScrollView.cpp @@ -15,24 +15,47 @@ QSK_SUBCONTROL( QskScrollView, HorizontalScrollHandle ) QSK_SUBCONTROL( QskScrollView, VerticalScrollBar ) QSK_SUBCONTROL( QskScrollView, VerticalScrollHandle ) -QSK_SYSTEM_STATE( QskScrollView, VerticalHandlePressed, QskAspect::FirstSystemState << 1 ) -QSK_SYSTEM_STATE( QskScrollView, HorizontalHandlePressed, QskAspect::FirstSystemState << 2 ) +QSK_SYSTEM_STATE( QskScrollView, Pressed, QskAspect::FirstSystemState << 1 ) class QskScrollView::PrivateData { public: - PrivateData() - : horizontalScrollBarPolicy( Qt::ScrollBarAsNeeded ) - , verticalScrollBarPolicy( Qt::ScrollBarAsNeeded ) - , isScrolling( 0 ) + inline void resetScrolling( QskScrollView* scrollView ) { + setScrolling( scrollView, 0, 0.0 ); } - Qt::ScrollBarPolicy horizontalScrollBarPolicy; - Qt::ScrollBarPolicy verticalScrollBarPolicy; + inline void setScrolling( QskScrollView* scrollView, int scrolling, qreal pos ) + { + if ( isScrolling == scrolling ) + return; + + QskAspect::Subcontrol subControl; + if ( ( isScrolling == Qt::Horizontal ) || ( scrolling == Qt::Horizontal ) ) + subControl = HorizontalScrollHandle; + else + subControl = VerticalScrollHandle; + + this->isScrolling = scrolling; + this->scrollPressPos = pos; + + scrollView->update(); + + auto oldStates = scrollView->skinStates(); + auto newStates = oldStates | QskScrollView::Pressed; + + if ( scrolling == 0 ) + qSwap( oldStates, newStates ); + + scrollView->startHintTransitions( { subControl }, oldStates, newStates ); + + } + + Qt::ScrollBarPolicy horizontalScrollBarPolicy = Qt::ScrollBarAsNeeded; + Qt::ScrollBarPolicy verticalScrollBarPolicy = Qt::ScrollBarAsNeeded; qreal scrollPressPos; - int isScrolling; + int isScrolling = 0; }; QskScrollView::QskScrollView( QQuickItem* parent ) @@ -88,6 +111,15 @@ bool QskScrollView::isScrolling( Qt::Orientation orientation ) const return m_data->isScrolling == orientation; } +QskAspect::States QskScrollView::scrollHandleStates( Qt::Orientation orientation ) const +{ + auto states = skinStates(); + if ( m_data->isScrolling == orientation ) + states |= Pressed; + + return states; +} + QRectF QskScrollView::viewContentsRect() const { // This code should be done in the skinlet. TODO ... @@ -107,10 +139,7 @@ void QskScrollView::mousePressEvent( QMouseEvent* event ) if ( handleRect.contains( mousePos ) ) { - m_data->isScrolling = Qt::Vertical; - m_data->scrollPressPos = mousePos.y(); - - setSkinStateFlag( VerticalHandlePressed, true ); + m_data->setScrolling( this, Qt::Vertical, mousePos.y() ); } else { @@ -135,10 +164,7 @@ void QskScrollView::mousePressEvent( QMouseEvent* event ) if ( handleRect.contains( mousePos ) ) { - m_data->isScrolling = Qt::Horizontal; - m_data->scrollPressPos = mousePos.x(); - - setSkinStateFlag( HorizontalHandlePressed, true ); + m_data->setScrolling( this, Qt::Horizontal, mousePos.x() ); } else { @@ -200,11 +226,12 @@ void QskScrollView::mouseReleaseEvent( QMouseEvent* event ) return; } - m_data->isScrolling = 0; - m_data->scrollPressPos = 0; + m_data->resetScrolling( this ); +} - setSkinStateFlag( HorizontalHandlePressed, false ); - setSkinStateFlag( VerticalHandlePressed, false ); +void QskScrollView::mouseUngrabEvent() +{ + m_data->resetScrolling( this ); } #ifndef QT_NO_WHEELEVENT diff --git a/src/controls/QskScrollView.h b/src/controls/QskScrollView.h index 15a47a3e..fe0dfa38 100644 --- a/src/controls/QskScrollView.h +++ b/src/controls/QskScrollView.h @@ -25,7 +25,7 @@ class QSK_EXPORT QskScrollView : public QskScrollBox HorizontalScrollBar, HorizontalScrollHandle, VerticalScrollBar, VerticalScrollHandle ) - QSK_STATES( VerticalHandlePressed, HorizontalHandlePressed ) + QSK_STATES( Pressed ) QskScrollView( QQuickItem* parent = nullptr ); ~QskScrollView() override; @@ -39,6 +39,7 @@ class QSK_EXPORT QskScrollView : public QskScrollBox Qt::Orientations scrollableOrientations() const; bool isScrolling( Qt::Orientation ) const; + QskAspect::States scrollHandleStates( Qt::Orientation ) const; QRectF viewContentsRect() const override; QskAnimationHint flickHint() const override; @@ -51,6 +52,7 @@ class QSK_EXPORT QskScrollView : public QskScrollBox void mouseMoveEvent( QMouseEvent* ) override; void mousePressEvent( QMouseEvent* ) override; void mouseReleaseEvent( QMouseEvent* ) override; + void mouseUngrabEvent() override; #ifndef QT_NO_WHEELEVENT QPointF scrollOffset( const QWheelEvent* ) const override; diff --git a/src/controls/QskScrollViewSkinlet.cpp b/src/controls/QskScrollViewSkinlet.cpp index a786c6a1..b1f2d7e5 100644 --- a/src/controls/QskScrollViewSkinlet.cpp +++ b/src/controls/QskScrollViewSkinlet.cpp @@ -9,6 +9,7 @@ #include "QskAspect.h" #include "QskQuick.h" #include "QskSGNode.h" +#include "QskSkinStateChanger.h" #include @@ -51,37 +52,27 @@ QskScrollViewSkinlet::~QskScrollViewSkinlet() = default; QRectF QskScrollViewSkinlet::subControlRect( const QskSkinnable* skinnable, const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const { + using Q = QskScrollView; + const auto scrollView = static_cast< const QskScrollView* >( skinnable ); - if ( subControl == QskScrollView::Panel ) - { + if ( subControl == Q::Panel ) return contentsRect; - } - if ( subControl == QskScrollView::Viewport ) - { + if ( subControl == Q::Viewport ) return viewportRect( scrollView, contentsRect ); - } - if ( subControl == QskScrollView::HorizontalScrollBar ) - { + if ( subControl == Q::HorizontalScrollBar ) return scrollBarRect( scrollView, contentsRect, Qt::Horizontal ); - } - if ( subControl == QskScrollView::HorizontalScrollHandle ) - { + if ( subControl == Q::HorizontalScrollHandle ) return scrollHandleRect( scrollView, contentsRect, Qt::Horizontal ); - } - if ( subControl == QskScrollView::VerticalScrollBar ) - { + if ( subControl == Q::VerticalScrollBar ) return scrollBarRect( scrollView, contentsRect, Qt::Vertical ); - } - if ( subControl == QskScrollView::VerticalScrollHandle ) - { + if ( subControl == Q::VerticalScrollHandle ) return scrollHandleRect( scrollView, contentsRect, Qt::Vertical ); - } return Inherited::subControlRect( skinnable, contentsRect, subControl ); } @@ -89,27 +80,41 @@ QRectF QskScrollViewSkinlet::subControlRect( const QskSkinnable* skinnable, QSGNode* QskScrollViewSkinlet::updateSubNode( const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const { + using Q = QskScrollView; + const auto scrollView = static_cast< const QskScrollView* >( skinnable ); switch ( nodeRole ) { case PanelRole: { - return updateBoxNode( skinnable, node, QskScrollView::Panel ); + return updateBoxNode( skinnable, node, Q::Panel ); } case ViewportRole: { - return updateBoxNode( skinnable, node, QskScrollView::Viewport ); + return updateBoxNode( skinnable, node, Q::Viewport ); } case HorizontalScrollHandleRole: { - return updateBoxNode( skinnable, node, QskScrollView::HorizontalScrollHandle ); + const auto rect = subControlRect( skinnable, + scrollView->contentsRect(), Q::HorizontalScrollHandle ); + + QskSkinStateChanger stateChanger( scrollView ); + stateChanger.setStates( scrollView->scrollHandleStates( Qt::Horizontal ) ); + + return updateBoxNode( skinnable, node, rect, Q::HorizontalScrollHandle ); } case VerticalScrollHandleRole: { - return updateBoxNode( skinnable, node, QskScrollView::VerticalScrollHandle ); + const auto rect = subControlRect( skinnable, + scrollView->contentsRect(), Q::VerticalScrollHandle ); + + QskSkinStateChanger stateChanger( scrollView ); + stateChanger.setStates( scrollView->scrollHandleStates( Qt::Vertical ) ); + + return updateBoxNode( skinnable, node, rect, Q::VerticalScrollHandle ); } case ContentsRootRole: @@ -236,22 +241,23 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView, const auto vRect = subControlRect( scrollView, contentsRect, QskScrollView::Viewport ); + const auto scrollableSize = scrollView->scrollableSize(); + QRectF handleRect; if ( orientation == Qt::Vertical ) { - const auto subControlBar = Q::VerticalScrollBar; + const auto sbRect = subControlRect( scrollView, contentsRect, Q::VerticalScrollBar ); - const auto sbRect = subControlRect( scrollView, contentsRect, subControlBar ); - const auto padding = scrollView->paddingHint( subControlBar ); - - const qreal h = scrollView->scrollableSize().height(); - - const qreal y1 = pos.y() / h; - const qreal y2 = ( pos.y() + vRect.height() ) / h; + QskSkinStateChanger stateChanger( scrollView ); + stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); + const auto padding = scrollView->paddingHint( Q::VerticalScrollBar ); const auto strut = scrollView->strutSizeHint( Q::VerticalScrollHandle ); + const qreal y1 = pos.y() / scrollableSize.height(); + const qreal y2 = ( pos.y() + vRect.height() ) / scrollableSize.height(); + qreal top, bottom; qskAlignedHandle( y1, y2, sbRect.height(), strut.height(), top, bottom ); @@ -262,15 +268,15 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView, } else { - const auto subControlBar = Q::HorizontalScrollBar; + const auto sbRect = subControlRect( scrollView, contentsRect, Q::HorizontalScrollBar ); - const auto sbRect = subControlRect( scrollView, contentsRect, subControlBar ); - const auto padding = scrollView->paddingHint( subControlBar ); + QskSkinStateChanger stateChanger( scrollView ); + stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); - const qreal w = scrollView->scrollableSize().width(); + const auto padding = scrollView->paddingHint( Q::HorizontalScrollBar ); - const qreal x1 = pos.x() / w; - const qreal x2 = ( pos.x() + vRect.width() ) / w; + const qreal x1 = pos.x() / scrollableSize.width(); + const qreal x2 = ( pos.x() + vRect.width() ) / scrollableSize.width(); const auto strut = scrollView->strutSizeHint( Q::HorizontalScrollHandle ); @@ -298,6 +304,9 @@ QRectF QskScrollViewSkinlet::scrollBarRect( const QskScrollView* scrollView, auto r = subControlRect( scrollView, contentsRect, Q::Panel ); + QskSkinStateChanger stateChanger( scrollView ); + stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); + if ( orientation == Qt::Horizontal ) { const qreal h = scrollView->metric( Q::HorizontalScrollBar | A::Size );