scrollbar hover events
This commit is contained in:
parent
bdef864bf3
commit
c6fb2f81c9
@ -1012,9 +1012,13 @@ void Editor::setupScrollView()
|
||||
// scroll bars
|
||||
for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } )
|
||||
{
|
||||
setMetric( subControl | A::Size, 12_dp );
|
||||
setPadding( subControl, 0 );
|
||||
setMetric( subControl | A::Size, 14 );
|
||||
setPadding( subControl, 2 );
|
||||
setMargin( subControl, 0 );
|
||||
|
||||
setPanel( subControl, Sunken );
|
||||
setBoxShape( subControl, 100, Qt::RelativeSize );
|
||||
setBoxBorderMetrics( subControl, 1 );
|
||||
}
|
||||
|
||||
// scrollbar handles
|
||||
@ -1024,6 +1028,8 @@ void Editor::setupScrollView()
|
||||
|
||||
setButton( subControl, Raised, bw );
|
||||
setButton( subControl | Q::Pressed, Sunken, bw );
|
||||
setBoxShape( subControl, 100, Qt::RelativeSize );
|
||||
setBoxShape( subControl | Q::Pressed, 100, Qt::RelativeSize );
|
||||
|
||||
const auto extent = 40_dp;
|
||||
|
||||
|
@ -17,60 +17,132 @@ QSK_SUBCONTROL( QskScrollView, VerticalScrollHandle )
|
||||
|
||||
QSK_SYSTEM_STATE( QskScrollView, Pressed, QskAspect::FirstSystemState << 1 )
|
||||
|
||||
static inline QskAspect::Subcontrol qskSubControlAt(
|
||||
const QskScrollView* scrollView, const QPointF& pos )
|
||||
{
|
||||
using Q = QskScrollView;
|
||||
|
||||
const auto rect = scrollView->contentsRect();
|
||||
|
||||
// order is important as the handles are inside the bars !
|
||||
|
||||
for ( auto subControl : { Q::VerticalScrollHandle, Q::VerticalScrollBar,
|
||||
Q::HorizontalScrollHandle, Q::HorizontalScrollBar } )
|
||||
{
|
||||
if ( scrollView->subControlRect( rect, subControl ).contains( pos ) )
|
||||
return subControl;
|
||||
}
|
||||
|
||||
return QskAspect::NoSubcontrol;
|
||||
}
|
||||
|
||||
class QskScrollView::PrivateData
|
||||
{
|
||||
public:
|
||||
inline void resetScrolling( QskScrollView* scrollView )
|
||||
{
|
||||
setScrolling( scrollView, 0, 0.0 );
|
||||
setScrolling( scrollView, QskAspect::NoSubcontrol, 0.0 );
|
||||
}
|
||||
|
||||
inline void setScrolling( QskScrollView* scrollView, int scrolling, qreal pos )
|
||||
inline void setScrolling( QskScrollView* scrollView,
|
||||
QskAspect::Subcontrol subControl, qreal pos )
|
||||
{
|
||||
if ( isScrolling == scrolling )
|
||||
if ( subControl == pressedSubControl )
|
||||
return;
|
||||
|
||||
Qt::Orientation orientation;
|
||||
|
||||
if ( ( isScrolling == Qt::Horizontal ) || ( scrolling == Qt::Horizontal ) )
|
||||
orientation = Qt::Horizontal;
|
||||
QskAspect::Subcontrol subControls[2];
|
||||
if ( subControl == VerticalScrollHandle || pressedSubControl == VerticalScrollHandle )
|
||||
{
|
||||
subControls[0] = VerticalScrollHandle;
|
||||
subControls[1] = VerticalScrollBar;
|
||||
}
|
||||
else
|
||||
orientation = Qt::Vertical;
|
||||
{
|
||||
subControls[0] = HorizontalScrollHandle;;
|
||||
subControls[1] = HorizontalScrollBar;
|
||||
}
|
||||
|
||||
this->isScrolling = scrolling;
|
||||
this->scrollPressPos = pos;
|
||||
pressedSubControl = subControl;
|
||||
scrollPressPos = pos;
|
||||
|
||||
scrollView->update();
|
||||
|
||||
auto oldStates = scrollView->skinStates();
|
||||
auto oldStates = scrollView->skinStates() | scrollView->scrollBarStates( subControl );
|
||||
auto newStates = oldStates | QskScrollView::Pressed;
|
||||
|
||||
if ( scrolling == 0 )
|
||||
if ( pressedSubControl == QskAspect::NoSubcontrol )
|
||||
qSwap( oldStates, newStates );
|
||||
|
||||
if ( orientation == Qt::Horizontal )
|
||||
scrollView->startHintTransitions( { subControls[0] }, oldStates, newStates );
|
||||
scrollView->startHintTransitions( { subControls[1] }, oldStates, newStates );
|
||||
}
|
||||
|
||||
void setHovered( QskScrollView* scrollView, QskAspect::Subcontrol subControl )
|
||||
{
|
||||
if ( subControl == this->hoveredSubControl )
|
||||
return;
|
||||
|
||||
QskAspect::Subcontrol subControls[2];
|
||||
if ( subControl == VerticalScrollHandle
|
||||
|| hoveredSubControl == VerticalScrollHandle
|
||||
|| subControl == VerticalScrollBar
|
||||
|| hoveredSubControl == VerticalScrollBar )
|
||||
{
|
||||
scrollView->startHintTransitions( { HorizontalScrollHandle }, oldStates, newStates );
|
||||
scrollView->startHintTransitions( { HorizontalScrollBar }, oldStates, newStates );
|
||||
subControls[0] = VerticalScrollHandle;
|
||||
subControls[1] = VerticalScrollBar;
|
||||
}
|
||||
else
|
||||
{
|
||||
scrollView->startHintTransitions( { VerticalScrollHandle }, oldStates, newStates );
|
||||
scrollView->startHintTransitions( { VerticalScrollBar }, oldStates, newStates );
|
||||
subControls[0] = HorizontalScrollHandle;;
|
||||
subControls[1] = HorizontalScrollBar;
|
||||
}
|
||||
|
||||
hoveredSubControl = subControl;
|
||||
|
||||
auto oldStates = scrollView->skinStates();
|
||||
auto newStates = oldStates | QskScrollView::Hovered;
|
||||
|
||||
if ( hoveredSubControl == QskAspect::NoSubcontrol )
|
||||
qSwap( oldStates, newStates );
|
||||
|
||||
scrollView->startHintTransitions( { subControls[0] }, oldStates, newStates );
|
||||
scrollView->startHintTransitions( { subControls[1] }, oldStates, newStates );
|
||||
}
|
||||
|
||||
bool hasState( QskAspect::Subcontrol subControl, QskAspect::State state ) const
|
||||
{
|
||||
if ( subControl == QskAspect::NoSubcontrol )
|
||||
return false;
|
||||
|
||||
const auto stateSubcontrol =
|
||||
( state == QskControl::Hovered ) ? hoveredSubControl : pressedSubControl;
|
||||
|
||||
if ( subControl == stateSubcontrol )
|
||||
return true;
|
||||
|
||||
if ( subControl == VerticalScrollBar )
|
||||
return stateSubcontrol == VerticalScrollHandle;
|
||||
|
||||
if ( subControl == HorizontalScrollBar )
|
||||
return stateSubcontrol == HorizontalScrollHandle;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ScrollBarPolicy horizontalScrollBarPolicy = Qt::ScrollBarAsNeeded;
|
||||
Qt::ScrollBarPolicy verticalScrollBarPolicy = Qt::ScrollBarAsNeeded;
|
||||
|
||||
qreal scrollPressPos;
|
||||
int isScrolling = 0;
|
||||
qreal scrollPressPos = 0.0;
|
||||
|
||||
QskAspect::Subcontrol pressedSubControl = QskAspect::NoSubcontrol;
|
||||
QskAspect::Subcontrol hoveredSubControl = QskAspect::NoSubcontrol;
|
||||
};
|
||||
|
||||
QskScrollView::QskScrollView( QQuickItem* parent )
|
||||
: Inherited( parent )
|
||||
, m_data( new PrivateData() )
|
||||
{
|
||||
setAcceptHoverEvents( true );
|
||||
}
|
||||
|
||||
QskScrollView::~QskScrollView()
|
||||
@ -117,15 +189,23 @@ Qt::ScrollBarPolicy QskScrollView::horizontalScrollBarPolicy() const
|
||||
|
||||
bool QskScrollView::isScrolling( Qt::Orientation orientation ) const
|
||||
{
|
||||
return m_data->isScrolling == orientation;
|
||||
if ( orientation == Qt::Vertical )
|
||||
return m_data->pressedSubControl == VerticalScrollHandle;
|
||||
else
|
||||
return m_data->pressedSubControl == HorizontalScrollHandle;
|
||||
}
|
||||
|
||||
QskAspect::States QskScrollView::scrollHandleStates( Qt::Orientation orientation ) const
|
||||
QskAspect::States QskScrollView::scrollBarStates(
|
||||
QskAspect::Subcontrol subControl ) const
|
||||
{
|
||||
auto states = skinStates();
|
||||
if ( m_data->isScrolling == orientation )
|
||||
|
||||
if ( m_data->hasState( subControl, Pressed ) )
|
||||
states |= Pressed;
|
||||
|
||||
if ( m_data->hasState( subControl, Hovered ) )
|
||||
states |= Hovered;
|
||||
|
||||
return states;
|
||||
}
|
||||
|
||||
@ -143,11 +223,11 @@ void QskScrollView::mousePressEvent( QMouseEvent* event )
|
||||
|
||||
if ( subControlRect( VerticalScrollBar ).contains( mousePos ) )
|
||||
{
|
||||
const QRectF handleRect = subControlRect( VerticalScrollHandle );
|
||||
const auto handleRect = subControlRect( VerticalScrollHandle );
|
||||
|
||||
if ( handleRect.contains( mousePos ) )
|
||||
{
|
||||
m_data->setScrolling( this, Qt::Vertical, mousePos.y() );
|
||||
m_data->setScrolling( this, VerticalScrollHandle, mousePos.y() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -172,7 +252,7 @@ void QskScrollView::mousePressEvent( QMouseEvent* event )
|
||||
|
||||
if ( handleRect.contains( mousePos ) )
|
||||
{
|
||||
m_data->setScrolling( this, Qt::Horizontal, mousePos.x() );
|
||||
m_data->setScrolling( this, HorizontalScrollHandle, mousePos.x() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -196,7 +276,7 @@ void QskScrollView::mousePressEvent( QMouseEvent* event )
|
||||
|
||||
void QskScrollView::mouseMoveEvent( QMouseEvent* event )
|
||||
{
|
||||
if ( !m_data->isScrolling )
|
||||
if ( m_data->pressedSubControl == QskAspect::NoSubcontrol )
|
||||
{
|
||||
Inherited::mouseMoveEvent( event );
|
||||
return;
|
||||
@ -205,7 +285,7 @@ void QskScrollView::mouseMoveEvent( QMouseEvent* event )
|
||||
const auto mousePos = qskMousePosition( event );
|
||||
QPointF pos = scrollPos();
|
||||
|
||||
if ( m_data->isScrolling == Qt::Horizontal )
|
||||
if ( m_data->pressedSubControl == HorizontalScrollHandle )
|
||||
{
|
||||
const qreal dx = mousePos.x() - m_data->scrollPressPos;
|
||||
const qreal w = subControlRect( HorizontalScrollBar ).width();
|
||||
@ -213,7 +293,7 @@ void QskScrollView::mouseMoveEvent( QMouseEvent* event )
|
||||
pos.rx() += dx / w * scrollableSize().width();
|
||||
m_data->scrollPressPos = mousePos.x();
|
||||
}
|
||||
else if ( m_data->isScrolling == Qt::Vertical )
|
||||
else
|
||||
{
|
||||
const qreal dy = mousePos.y() - m_data->scrollPressPos;
|
||||
const qreal h = subControlRect( VerticalScrollBar ).height();
|
||||
@ -228,7 +308,7 @@ void QskScrollView::mouseMoveEvent( QMouseEvent* event )
|
||||
|
||||
void QskScrollView::mouseReleaseEvent( QMouseEvent* event )
|
||||
{
|
||||
if ( !m_data->isScrolling )
|
||||
if ( m_data->pressedSubControl == QskAspect::NoSubcontrol )
|
||||
{
|
||||
Inherited::mouseReleaseEvent( event );
|
||||
return;
|
||||
@ -242,6 +322,23 @@ void QskScrollView::mouseUngrabEvent()
|
||||
m_data->resetScrolling( this );
|
||||
}
|
||||
|
||||
void QskScrollView::hoverEnterEvent( QHoverEvent* event )
|
||||
{
|
||||
const auto subControl = qskSubControlAt( this, qskHoverPosition( event ) );
|
||||
m_data->setHovered( this, subControl );
|
||||
}
|
||||
|
||||
void QskScrollView::hoverMoveEvent( QHoverEvent* event )
|
||||
{
|
||||
const auto subControl = qskSubControlAt( this, qskHoverPosition( event ) );
|
||||
m_data->setHovered( this, subControl );
|
||||
}
|
||||
|
||||
void QskScrollView::hoverLeaveEvent( QHoverEvent* )
|
||||
{
|
||||
m_data->setHovered( this, QskAspect::NoSubcontrol );
|
||||
}
|
||||
|
||||
#ifndef QT_NO_WHEELEVENT
|
||||
|
||||
QPointF QskScrollView::scrollOffset( const QWheelEvent* event ) const
|
||||
|
@ -39,7 +39,7 @@ class QSK_EXPORT QskScrollView : public QskScrollBox
|
||||
Qt::Orientations scrollableOrientations() const;
|
||||
|
||||
bool isScrolling( Qt::Orientation ) const;
|
||||
QskAspect::States scrollHandleStates( Qt::Orientation ) const;
|
||||
QskAspect::States scrollBarStates( QskAspect::Subcontrol ) const;
|
||||
|
||||
QRectF viewContentsRect() const override;
|
||||
QskAnimationHint flickHint() const override;
|
||||
@ -54,6 +54,10 @@ 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
|
||||
|
@ -39,14 +39,16 @@ static void qskAlignedHandle( qreal start, qreal end,
|
||||
}
|
||||
}
|
||||
|
||||
static inline Qt::Orientation qskSubcontrolOrientation( QskAspect::Subcontrol subControl )
|
||||
static qreal qskScrollBarExtent(
|
||||
const QskScrollView* scrollView, Qt::Orientation orientation )
|
||||
{
|
||||
using Q = QskScrollView;
|
||||
const auto subControl = ( orientation == Qt::Horizontal )
|
||||
? QskScrollView::HorizontalScrollBar : QskScrollView::VerticalScrollBar;
|
||||
|
||||
if ( subControl == Q::HorizontalScrollBar || subControl == Q::HorizontalScrollHandle )
|
||||
return Qt::Horizontal;
|
||||
else
|
||||
return Qt::Vertical;
|
||||
QskSkinStateChanger stateChanger( scrollView );
|
||||
stateChanger.setStates( scrollView->scrollBarStates( subControl ) );
|
||||
|
||||
return scrollView->metric( subControl | QskAspect::Size );
|
||||
}
|
||||
|
||||
QskScrollViewSkinlet::QskScrollViewSkinlet( QskSkin* skin )
|
||||
@ -128,10 +130,8 @@ QSGNode* QskScrollViewSkinlet::updateScrollBarNode( const QskScrollView* scrollV
|
||||
const auto rect = subControlRect( scrollView,
|
||||
scrollView->contentsRect(), subControl );
|
||||
|
||||
const auto orientation = qskSubcontrolOrientation( subControl );
|
||||
|
||||
QskSkinStateChanger stateChanger( scrollView );
|
||||
stateChanger.setStates( scrollView->scrollHandleStates( orientation ) );
|
||||
stateChanger.setStates( scrollView->scrollBarStates( subControl ) );
|
||||
|
||||
return updateBoxNode( scrollView, node, rect, subControl );
|
||||
}
|
||||
@ -254,7 +254,7 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView,
|
||||
const auto sbRect = subControlRect( scrollView, contentsRect, Q::VerticalScrollBar );
|
||||
|
||||
QskSkinStateChanger stateChanger( scrollView );
|
||||
stateChanger.setStates( scrollView->scrollHandleStates( orientation ) );
|
||||
stateChanger.setStates( scrollView->scrollBarStates( Q::VerticalScrollBar ) );
|
||||
|
||||
const auto padding = scrollView->paddingHint( Q::VerticalScrollBar );
|
||||
const auto strut = scrollView->strutSizeHint( Q::VerticalScrollHandle );
|
||||
@ -275,7 +275,7 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView,
|
||||
const auto sbRect = subControlRect( scrollView, contentsRect, Q::HorizontalScrollBar );
|
||||
|
||||
QskSkinStateChanger stateChanger( scrollView );
|
||||
stateChanger.setStates( scrollView->scrollHandleStates( orientation ) );
|
||||
stateChanger.setStates( scrollView->scrollBarStates( Q::HorizontalScrollBar ) );
|
||||
|
||||
const auto padding = scrollView->paddingHint( Q::HorizontalScrollBar );
|
||||
|
||||
@ -299,7 +299,6 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView,
|
||||
QRectF QskScrollViewSkinlet::scrollBarRect( const QskScrollView* scrollView,
|
||||
const QRectF& contentsRect, Qt::Orientation orientation ) const
|
||||
{
|
||||
using A = QskAspect;
|
||||
using Q = QskScrollView;
|
||||
|
||||
const auto scrollOrientations = scrollView->scrollableOrientations();
|
||||
@ -308,28 +307,25 @@ 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 );
|
||||
const qreal h = qskScrollBarExtent( scrollView, Qt::Horizontal );
|
||||
r.setTop( r.bottom() - h );
|
||||
|
||||
if ( scrollOrientations & Qt::Vertical )
|
||||
{
|
||||
const qreal w = scrollView->metric( Q::VerticalScrollBar | A::Size );
|
||||
const qreal w = qskScrollBarExtent( scrollView, Qt::Vertical );
|
||||
r.setRight( r.right() - w );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const qreal w = scrollView->metric( Q::VerticalScrollBar | A::Size );
|
||||
const qreal w = qskScrollBarExtent( scrollView, Qt::Vertical );
|
||||
r.setLeft( r.right() - w );
|
||||
|
||||
if ( scrollOrientations & Qt::Horizontal )
|
||||
{
|
||||
const qreal h = scrollView->metric( Q::HorizontalScrollBar | A::Size );
|
||||
const qreal h = qskScrollBarExtent( scrollView, Qt::Horizontal );
|
||||
r.setBottom( r.bottom() - h );
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user