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;
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 );
}

View File

@ -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

View File

@ -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;

View File

@ -9,6 +9,7 @@
#include "QskAspect.h"
#include "QskQuick.h"
#include "QskSGNode.h"
#include "QskSkinStateChanger.h"
#include <qsgnode.h>
@ -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 );