Fluent2/Material3 need specific settings for Hovered/Pressed states of

scrollbar handles ( vertical/horizontal ) and list box cells. Having 2 * 3
different states is not working properly and we need to do some manual
coding to limit the states. This first commit works with Pressed only -
Hovered will be added.
This commit is contained in:
Uwe Rathmann 2023-06-30 14:51:03 +02:00
parent 1634335a49
commit 9a37a1ef9d
4 changed files with 97 additions and 64 deletions

View File

@ -1023,19 +1023,14 @@ void Editor::setupScrollView()
const qreal bw = 1.0; const qreal bw = 1.0;
setButton( subControl, Raised, bw ); setButton( subControl, Raised, bw );
setButton( subControl | Q::Pressed, Sunken, bw );
const auto extent = 40_dp; const auto extent = 40_dp;
if ( subControl == Q::HorizontalScrollHandle ) if ( subControl == Q::HorizontalScrollHandle )
{
setStrutSize( subControl, extent, 0.0 ); setStrutSize( subControl, extent, 0.0 );
setButton( subControl | Q::HorizontalHandlePressed, Sunken, bw );
}
else else
{
setStrutSize( subControl, 0.0, extent ); setStrutSize( subControl, 0.0, extent );
setButton( subControl | Q::VerticalHandlePressed, Sunken, bw );
}
setAnimation( subControl | A::Color, qskDuration ); setAnimation( subControl | A::Color, qskDuration );
} }

View File

@ -15,24 +15,47 @@ QSK_SUBCONTROL( QskScrollView, HorizontalScrollHandle )
QSK_SUBCONTROL( QskScrollView, VerticalScrollBar ) QSK_SUBCONTROL( QskScrollView, VerticalScrollBar )
QSK_SUBCONTROL( QskScrollView, VerticalScrollHandle ) QSK_SUBCONTROL( QskScrollView, VerticalScrollHandle )
QSK_SYSTEM_STATE( QskScrollView, VerticalHandlePressed, QskAspect::FirstSystemState << 1 ) QSK_SYSTEM_STATE( QskScrollView, Pressed, QskAspect::FirstSystemState << 1 )
QSK_SYSTEM_STATE( QskScrollView, HorizontalHandlePressed, QskAspect::FirstSystemState << 2 )
class QskScrollView::PrivateData class QskScrollView::PrivateData
{ {
public: public:
PrivateData() inline void resetScrolling( QskScrollView* scrollView )
: horizontalScrollBarPolicy( Qt::ScrollBarAsNeeded )
, verticalScrollBarPolicy( Qt::ScrollBarAsNeeded )
, isScrolling( 0 )
{ {
setScrolling( scrollView, 0, 0.0 );
} }
Qt::ScrollBarPolicy horizontalScrollBarPolicy; inline void setScrolling( QskScrollView* scrollView, int scrolling, qreal pos )
Qt::ScrollBarPolicy verticalScrollBarPolicy; {
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; qreal scrollPressPos;
int isScrolling; int isScrolling = 0;
}; };
QskScrollView::QskScrollView( QQuickItem* parent ) QskScrollView::QskScrollView( QQuickItem* parent )
@ -88,6 +111,15 @@ bool QskScrollView::isScrolling( Qt::Orientation orientation ) const
return m_data->isScrolling == orientation; 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 QRectF QskScrollView::viewContentsRect() const
{ {
// This code should be done in the skinlet. TODO ... // This code should be done in the skinlet. TODO ...
@ -107,10 +139,7 @@ void QskScrollView::mousePressEvent( QMouseEvent* event )
if ( handleRect.contains( mousePos ) ) if ( handleRect.contains( mousePos ) )
{ {
m_data->isScrolling = Qt::Vertical; m_data->setScrolling( this, Qt::Vertical, mousePos.y() );
m_data->scrollPressPos = mousePos.y();
setSkinStateFlag( VerticalHandlePressed, true );
} }
else else
{ {
@ -135,10 +164,7 @@ void QskScrollView::mousePressEvent( QMouseEvent* event )
if ( handleRect.contains( mousePos ) ) if ( handleRect.contains( mousePos ) )
{ {
m_data->isScrolling = Qt::Horizontal; m_data->setScrolling( this, Qt::Horizontal, mousePos.x() );
m_data->scrollPressPos = mousePos.x();
setSkinStateFlag( HorizontalHandlePressed, true );
} }
else else
{ {
@ -200,11 +226,12 @@ void QskScrollView::mouseReleaseEvent( QMouseEvent* event )
return; return;
} }
m_data->isScrolling = 0; m_data->resetScrolling( this );
m_data->scrollPressPos = 0; }
setSkinStateFlag( HorizontalHandlePressed, false ); void QskScrollView::mouseUngrabEvent()
setSkinStateFlag( VerticalHandlePressed, false ); {
m_data->resetScrolling( this );
} }
#ifndef QT_NO_WHEELEVENT #ifndef QT_NO_WHEELEVENT

View File

@ -25,7 +25,7 @@ class QSK_EXPORT QskScrollView : public QskScrollBox
HorizontalScrollBar, HorizontalScrollHandle, HorizontalScrollBar, HorizontalScrollHandle,
VerticalScrollBar, VerticalScrollHandle ) VerticalScrollBar, VerticalScrollHandle )
QSK_STATES( VerticalHandlePressed, HorizontalHandlePressed ) QSK_STATES( Pressed )
QskScrollView( QQuickItem* parent = nullptr ); QskScrollView( QQuickItem* parent = nullptr );
~QskScrollView() override; ~QskScrollView() override;
@ -39,6 +39,7 @@ class QSK_EXPORT QskScrollView : public QskScrollBox
Qt::Orientations scrollableOrientations() const; Qt::Orientations scrollableOrientations() const;
bool isScrolling( Qt::Orientation ) const; bool isScrolling( Qt::Orientation ) const;
QskAspect::States scrollHandleStates( Qt::Orientation ) const;
QRectF viewContentsRect() const override; QRectF viewContentsRect() const override;
QskAnimationHint flickHint() const override; QskAnimationHint flickHint() const override;
@ -51,6 +52,7 @@ class QSK_EXPORT QskScrollView : public QskScrollBox
void mouseMoveEvent( QMouseEvent* ) override; void mouseMoveEvent( QMouseEvent* ) override;
void mousePressEvent( QMouseEvent* ) override; void mousePressEvent( QMouseEvent* ) override;
void mouseReleaseEvent( QMouseEvent* ) override; void mouseReleaseEvent( QMouseEvent* ) override;
void mouseUngrabEvent() override;
#ifndef QT_NO_WHEELEVENT #ifndef QT_NO_WHEELEVENT
QPointF scrollOffset( const QWheelEvent* ) const override; QPointF scrollOffset( const QWheelEvent* ) const override;

View File

@ -9,6 +9,7 @@
#include "QskAspect.h" #include "QskAspect.h"
#include "QskQuick.h" #include "QskQuick.h"
#include "QskSGNode.h" #include "QskSGNode.h"
#include "QskSkinStateChanger.h"
#include <qsgnode.h> #include <qsgnode.h>
@ -51,37 +52,27 @@ QskScrollViewSkinlet::~QskScrollViewSkinlet() = default;
QRectF QskScrollViewSkinlet::subControlRect( const QskSkinnable* skinnable, QRectF QskScrollViewSkinlet::subControlRect( const QskSkinnable* skinnable,
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
{ {
using Q = QskScrollView;
const auto scrollView = static_cast< const QskScrollView* >( skinnable ); const auto scrollView = static_cast< const QskScrollView* >( skinnable );
if ( subControl == QskScrollView::Panel ) if ( subControl == Q::Panel )
{
return contentsRect; return contentsRect;
}
if ( subControl == QskScrollView::Viewport ) if ( subControl == Q::Viewport )
{
return viewportRect( scrollView, contentsRect ); return viewportRect( scrollView, contentsRect );
}
if ( subControl == QskScrollView::HorizontalScrollBar ) if ( subControl == Q::HorizontalScrollBar )
{
return scrollBarRect( scrollView, contentsRect, Qt::Horizontal ); return scrollBarRect( scrollView, contentsRect, Qt::Horizontal );
}
if ( subControl == QskScrollView::HorizontalScrollHandle ) if ( subControl == Q::HorizontalScrollHandle )
{
return scrollHandleRect( scrollView, contentsRect, Qt::Horizontal ); return scrollHandleRect( scrollView, contentsRect, Qt::Horizontal );
}
if ( subControl == QskScrollView::VerticalScrollBar ) if ( subControl == Q::VerticalScrollBar )
{
return scrollBarRect( scrollView, contentsRect, Qt::Vertical ); return scrollBarRect( scrollView, contentsRect, Qt::Vertical );
}
if ( subControl == QskScrollView::VerticalScrollHandle ) if ( subControl == Q::VerticalScrollHandle )
{
return scrollHandleRect( scrollView, contentsRect, Qt::Vertical ); return scrollHandleRect( scrollView, contentsRect, Qt::Vertical );
}
return Inherited::subControlRect( skinnable, contentsRect, subControl ); return Inherited::subControlRect( skinnable, contentsRect, subControl );
} }
@ -89,27 +80,41 @@ QRectF QskScrollViewSkinlet::subControlRect( const QskSkinnable* skinnable,
QSGNode* QskScrollViewSkinlet::updateSubNode( QSGNode* QskScrollViewSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{ {
using Q = QskScrollView;
const auto scrollView = static_cast< const QskScrollView* >( skinnable ); const auto scrollView = static_cast< const QskScrollView* >( skinnable );
switch ( nodeRole ) switch ( nodeRole )
{ {
case PanelRole: case PanelRole:
{ {
return updateBoxNode( skinnable, node, QskScrollView::Panel ); return updateBoxNode( skinnable, node, Q::Panel );
} }
case ViewportRole: case ViewportRole:
{ {
return updateBoxNode( skinnable, node, QskScrollView::Viewport ); return updateBoxNode( skinnable, node, Q::Viewport );
} }
case HorizontalScrollHandleRole: 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: 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: case ContentsRootRole:
@ -236,22 +241,23 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView,
const auto vRect = subControlRect( const auto vRect = subControlRect(
scrollView, contentsRect, QskScrollView::Viewport ); scrollView, contentsRect, QskScrollView::Viewport );
const auto scrollableSize = scrollView->scrollableSize();
QRectF handleRect; QRectF handleRect;
if ( orientation == Qt::Vertical ) if ( orientation == Qt::Vertical )
{ {
const auto subControlBar = Q::VerticalScrollBar; const auto sbRect = subControlRect( scrollView, contentsRect, Q::VerticalScrollBar );
const auto sbRect = subControlRect( scrollView, contentsRect, subControlBar ); QskSkinStateChanger stateChanger( scrollView );
const auto padding = scrollView->paddingHint( subControlBar ); stateChanger.setStates( scrollView->scrollHandleStates( orientation ) );
const qreal h = scrollView->scrollableSize().height();
const qreal y1 = pos.y() / h;
const qreal y2 = ( pos.y() + vRect.height() ) / h;
const auto padding = scrollView->paddingHint( Q::VerticalScrollBar );
const auto strut = scrollView->strutSizeHint( Q::VerticalScrollHandle ); 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; qreal top, bottom;
qskAlignedHandle( y1, y2, sbRect.height(), strut.height(), top, bottom ); qskAlignedHandle( y1, y2, sbRect.height(), strut.height(), top, bottom );
@ -262,15 +268,15 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView,
} }
else else
{ {
const auto subControlBar = Q::HorizontalScrollBar; const auto sbRect = subControlRect( scrollView, contentsRect, Q::HorizontalScrollBar );
const auto sbRect = subControlRect( scrollView, contentsRect, subControlBar ); QskSkinStateChanger stateChanger( scrollView );
const auto padding = scrollView->paddingHint( subControlBar ); 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 x1 = pos.x() / scrollableSize.width();
const qreal x2 = ( pos.x() + vRect.width() ) / w; const qreal x2 = ( pos.x() + vRect.width() ) / scrollableSize.width();
const auto strut = scrollView->strutSizeHint( Q::HorizontalScrollHandle ); const auto strut = scrollView->strutSizeHint( Q::HorizontalScrollHandle );
@ -298,6 +304,9 @@ QRectF QskScrollViewSkinlet::scrollBarRect( const QskScrollView* scrollView,
auto r = subControlRect( scrollView, contentsRect, Q::Panel ); auto r = subControlRect( scrollView, contentsRect, Q::Panel );
QskSkinStateChanger stateChanger( scrollView );
stateChanger.setStates( scrollView->scrollHandleStates( orientation ) );
if ( orientation == Qt::Horizontal ) if ( orientation == Qt::Horizontal )
{ {
const qreal h = scrollView->metric( Q::HorizontalScrollBar | A::Size ); const qreal h = scrollView->metric( Q::HorizontalScrollBar | A::Size );