2017-07-21 18:21:34 +02:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "QskScrollView.h"
|
2018-01-16 12:13:38 +01:00
|
|
|
#include "QskAnimationHint.h"
|
2018-08-03 08:15:28 +02:00
|
|
|
#include "QskBoxBorderMetrics.h"
|
2020-10-25 17:35:50 +01:00
|
|
|
#include "QskEvent.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
QSK_SUBCONTROL( QskScrollView, Panel )
|
|
|
|
QSK_SUBCONTROL( QskScrollView, Viewport )
|
|
|
|
QSK_SUBCONTROL( QskScrollView, HorizontalScrollBar )
|
|
|
|
QSK_SUBCONTROL( QskScrollView, HorizontalScrollHandle )
|
|
|
|
QSK_SUBCONTROL( QskScrollView, VerticalScrollBar )
|
|
|
|
QSK_SUBCONTROL( QskScrollView, VerticalScrollHandle )
|
|
|
|
|
2019-04-02 17:50:08 +02:00
|
|
|
QSK_SYSTEM_STATE( QskScrollView, VerticalHandlePressed, QskAspect::FirstSystemState << 1 )
|
|
|
|
QSK_SYSTEM_STATE( QskScrollView, HorizontalHandlePressed, QskAspect::FirstSystemState << 2 )
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
class QskScrollView::PrivateData
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
public:
|
|
|
|
PrivateData()
|
|
|
|
: horizontalScrollBarPolicy( Qt::ScrollBarAsNeeded )
|
|
|
|
, verticalScrollBarPolicy( Qt::ScrollBarAsNeeded )
|
|
|
|
, isScrolling( 0 )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Qt::ScrollBarPolicy horizontalScrollBarPolicy;
|
|
|
|
Qt::ScrollBarPolicy verticalScrollBarPolicy;
|
|
|
|
|
|
|
|
qreal scrollPressPos;
|
|
|
|
int isScrolling;
|
|
|
|
};
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskScrollView::QskScrollView( QQuickItem* parent )
|
|
|
|
: Inherited( parent )
|
|
|
|
, m_data( new PrivateData() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QskScrollView::~QskScrollView()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-03-10 16:09:35 +01:00
|
|
|
QskAnimationHint QskScrollView::flickHint() const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-03-10 16:09:35 +01:00
|
|
|
return effectiveAnimation( QskAspect::Metric,
|
|
|
|
QskScrollView::Viewport, QskAspect::NoState );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskScrollView::setVerticalScrollBarPolicy( Qt::ScrollBarPolicy policy )
|
|
|
|
{
|
|
|
|
if ( policy != m_data->verticalScrollBarPolicy )
|
|
|
|
{
|
|
|
|
m_data->verticalScrollBarPolicy = policy;
|
|
|
|
update();
|
|
|
|
|
|
|
|
Q_EMIT verticalScrollBarPolicyChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Qt::ScrollBarPolicy QskScrollView::verticalScrollBarPolicy() const
|
|
|
|
{
|
|
|
|
return m_data->verticalScrollBarPolicy;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskScrollView::setHorizontalScrollBarPolicy( Qt::ScrollBarPolicy policy )
|
|
|
|
{
|
|
|
|
if ( policy != m_data->horizontalScrollBarPolicy )
|
|
|
|
{
|
|
|
|
m_data->horizontalScrollBarPolicy = policy;
|
|
|
|
update();
|
|
|
|
|
|
|
|
Q_EMIT horizontalScrollBarPolicyChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Qt::ScrollBarPolicy QskScrollView::horizontalScrollBarPolicy() const
|
|
|
|
{
|
|
|
|
return m_data->horizontalScrollBarPolicy;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskScrollView::isScrolling( Qt::Orientation orientation ) const
|
|
|
|
{
|
|
|
|
return m_data->isScrolling == orientation;
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF QskScrollView::viewContentsRect() const
|
|
|
|
{
|
2017-10-17 17:34:00 +02:00
|
|
|
// This code should be done in the skinlet. TODO ...
|
2017-10-18 20:00:06 +02:00
|
|
|
const qreal bw = boxBorderMetricsHint( Viewport ).widthAt( Qt::TopEdge );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
const QRectF r = subControlRect( Viewport );
|
2017-07-21 18:21:34 +02:00
|
|
|
return r.adjusted( bw, bw, -bw, -bw );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskScrollView::mousePressEvent( QMouseEvent* event )
|
|
|
|
{
|
2020-10-23 13:20:51 +02:00
|
|
|
const auto mousePos = qskMousePosition( event );
|
|
|
|
|
|
|
|
if ( subControlRect( VerticalScrollBar ).contains( mousePos ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-08-28 10:15:47 +02:00
|
|
|
const QRectF handleRect = subControlRect( VerticalScrollHandle );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-10-23 13:20:51 +02:00
|
|
|
if ( handleRect.contains( mousePos ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
m_data->isScrolling = Qt::Vertical;
|
2020-10-23 13:20:51 +02:00
|
|
|
m_data->scrollPressPos = mousePos.y();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
setSkinStateFlag( VerticalHandlePressed, true );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const QRectF vRect = viewContentsRect();
|
|
|
|
|
2020-03-10 16:09:35 +01:00
|
|
|
qreal y = scrollPos().y();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-10-23 13:20:51 +02:00
|
|
|
if ( mousePos.y() < handleRect.top() )
|
2017-07-21 18:21:34 +02:00
|
|
|
y -= vRect.height();
|
|
|
|
else
|
|
|
|
y += vRect.height();
|
|
|
|
|
2020-03-10 16:09:35 +01:00
|
|
|
setScrollPos( QPointF( scrollPos().x(), y ) );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-10-23 13:20:51 +02:00
|
|
|
if ( subControlRect( HorizontalScrollBar ).contains( mousePos ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-08-28 10:15:47 +02:00
|
|
|
const QRectF handleRect = subControlRect( HorizontalScrollHandle );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-10-23 13:20:51 +02:00
|
|
|
if ( handleRect.contains( mousePos ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
m_data->isScrolling = Qt::Horizontal;
|
2020-10-23 13:20:51 +02:00
|
|
|
m_data->scrollPressPos = mousePos.x();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
setSkinStateFlag( HorizontalHandlePressed, true );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const QRectF vRect = viewContentsRect();
|
|
|
|
|
2020-03-10 16:09:35 +01:00
|
|
|
qreal x = scrollPos().x();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-10-23 13:20:51 +02:00
|
|
|
if ( mousePos.x() < handleRect.left() )
|
2017-07-21 18:21:34 +02:00
|
|
|
x -= vRect.width();
|
|
|
|
else
|
|
|
|
x += vRect.width();
|
|
|
|
|
2020-03-10 16:09:35 +01:00
|
|
|
setScrollPos( QPointF( x, scrollPos().y() ) );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
2019-03-07 11:21:45 +01:00
|
|
|
|
|
|
|
return;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
2018-12-13 19:10:18 +01:00
|
|
|
|
|
|
|
Inherited::mousePressEvent( event );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskScrollView::mouseMoveEvent( QMouseEvent* event )
|
|
|
|
{
|
|
|
|
if ( !m_data->isScrolling )
|
|
|
|
{
|
|
|
|
Inherited::mouseMoveEvent( event );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-10-23 13:20:51 +02:00
|
|
|
const auto mousePos = qskMousePosition( event );
|
2020-03-10 16:09:35 +01:00
|
|
|
QPointF pos = scrollPos();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
if ( m_data->isScrolling == Qt::Horizontal )
|
|
|
|
{
|
2020-10-23 13:20:51 +02:00
|
|
|
const qreal dx = mousePos.x() - m_data->scrollPressPos;
|
2017-08-28 10:15:47 +02:00
|
|
|
const qreal w = subControlRect( HorizontalScrollBar ).width();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-03-10 16:09:35 +01:00
|
|
|
pos.rx() += dx / w * scrollableSize().width();
|
2020-10-23 13:20:51 +02:00
|
|
|
m_data->scrollPressPos = mousePos.x();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
else if ( m_data->isScrolling == Qt::Vertical )
|
|
|
|
{
|
2020-10-23 13:20:51 +02:00
|
|
|
const qreal dy = mousePos.y() - m_data->scrollPressPos;
|
2017-08-28 10:15:47 +02:00
|
|
|
const qreal h = subControlRect( VerticalScrollBar ).height();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-03-10 16:09:35 +01:00
|
|
|
pos.ry() += dy / h * scrollableSize().height();
|
2020-10-23 13:20:51 +02:00
|
|
|
m_data->scrollPressPos = mousePos.y();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-03-10 16:09:35 +01:00
|
|
|
if ( pos != scrollPos() )
|
2017-07-21 18:21:34 +02:00
|
|
|
setScrollPos( pos );
|
|
|
|
}
|
|
|
|
|
2018-12-13 19:10:18 +01:00
|
|
|
void QskScrollView::mouseReleaseEvent( QMouseEvent* event )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-12-13 19:10:18 +01:00
|
|
|
if ( !m_data->isScrolling )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-12-13 19:10:18 +01:00
|
|
|
Inherited::mouseReleaseEvent( event );
|
|
|
|
return;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
2018-12-13 19:10:18 +01:00
|
|
|
|
|
|
|
m_data->isScrolling = 0;
|
|
|
|
m_data->scrollPressPos = 0;
|
|
|
|
|
|
|
|
setSkinStateFlag( HorizontalHandlePressed, false );
|
|
|
|
setSkinStateFlag( VerticalHandlePressed, false );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef QT_NO_WHEELEVENT
|
|
|
|
|
2022-01-07 15:34:13 +01:00
|
|
|
QPointF QskScrollView::scrollOffset( const QWheelEvent* event ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-01-03 15:05:35 +01:00
|
|
|
QPointF offset;
|
|
|
|
|
2022-01-05 11:59:32 +01:00
|
|
|
const auto pos = qskWheelPosition( event );
|
2022-01-12 13:29:42 +01:00
|
|
|
const auto viewRect = viewContentsRect();
|
2020-10-25 17:35:50 +01:00
|
|
|
|
2022-01-05 11:59:32 +01:00
|
|
|
if ( subControlRect( VerticalScrollBar ).contains( pos ) )
|
2018-01-03 15:05:35 +01:00
|
|
|
{
|
2022-01-10 14:59:22 +01:00
|
|
|
const auto steps = qskWheelSteps( event );
|
2022-01-12 13:29:42 +01:00
|
|
|
offset.setY( steps );
|
2018-01-03 15:05:35 +01:00
|
|
|
}
|
2022-01-05 11:59:32 +01:00
|
|
|
else if ( subControlRect( HorizontalScrollBar ).contains( pos ) )
|
2018-01-03 15:05:35 +01:00
|
|
|
{
|
2022-01-10 14:59:22 +01:00
|
|
|
const auto steps = qskWheelSteps( event );
|
2022-01-12 13:29:42 +01:00
|
|
|
offset.setX( steps );
|
2018-01-03 15:05:35 +01:00
|
|
|
}
|
2022-01-12 13:29:42 +01:00
|
|
|
else if ( viewRect.contains( pos ) )
|
2018-01-11 14:16:20 +01:00
|
|
|
{
|
2022-01-12 13:29:42 +01:00
|
|
|
offset = event->pixelDelta();
|
|
|
|
if ( offset.isNull() )
|
|
|
|
offset = event->angleDelta() / QWheelEvent::DefaultDeltasPerStep;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !offset.isNull() )
|
|
|
|
{
|
|
|
|
const auto vs = viewRect.size() / 3.0;
|
|
|
|
|
|
|
|
offset.rx() *= vs.width();
|
|
|
|
offset.ry() *= vs.height();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2022-01-07 15:34:13 +01:00
|
|
|
return offset;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-03-10 16:09:35 +01:00
|
|
|
#endif
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
Qt::Orientations QskScrollView::scrollableOrientations() const
|
|
|
|
{
|
2018-11-17 09:22:11 +01:00
|
|
|
// layoutRect ???
|
2017-07-21 18:21:34 +02:00
|
|
|
const QRectF vr = contentsRect();
|
|
|
|
|
2018-11-17 09:22:11 +01:00
|
|
|
auto policyVertical = m_data->verticalScrollBarPolicy;
|
|
|
|
auto policyHorizontal = m_data->horizontalScrollBarPolicy;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2018-11-17 09:22:11 +01:00
|
|
|
if ( policyVertical == Qt::ScrollBarAsNeeded )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-11-17 09:22:11 +01:00
|
|
|
qreal height = vr.height();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2018-11-17 09:22:11 +01:00
|
|
|
if ( policyHorizontal == Qt::ScrollBarAlwaysOn )
|
|
|
|
height -= metric( HorizontalScrollBar | QskAspect::Size );
|
|
|
|
|
2020-03-10 16:09:35 +01:00
|
|
|
if ( scrollableSize().height() > height )
|
2018-11-17 09:22:11 +01:00
|
|
|
policyVertical = Qt::ScrollBarAlwaysOn;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-11-17 09:22:11 +01:00
|
|
|
if ( policyHorizontal == Qt::ScrollBarAsNeeded )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-11-17 09:22:11 +01:00
|
|
|
qreal width = vr.width();
|
|
|
|
|
|
|
|
if ( policyVertical == Qt::ScrollBarAlwaysOn )
|
|
|
|
width -= metric( VerticalScrollBar | QskAspect::Size );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-03-10 16:09:35 +01:00
|
|
|
if ( scrollableSize().width() > width )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-11-17 09:22:11 +01:00
|
|
|
policyHorizontal = Qt::ScrollBarAlwaysOn;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
// we have to check the vertical once more
|
|
|
|
|
2018-11-17 09:22:11 +01:00
|
|
|
if ( ( policyVertical == Qt::ScrollBarAsNeeded ) &&
|
2020-03-10 16:09:35 +01:00
|
|
|
( scrollableSize().height() >
|
2018-08-03 08:15:28 +02:00
|
|
|
vr.height() - metric( HorizontalScrollBar | QskAspect::Size ) ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-11-17 09:22:11 +01:00
|
|
|
policyVertical = Qt::ScrollBarAlwaysOn;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-17 09:22:11 +01:00
|
|
|
Qt::Orientations orientations;
|
|
|
|
|
|
|
|
if ( policyHorizontal == Qt::ScrollBarAlwaysOn )
|
|
|
|
orientations |= Qt::Horizontal;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2018-11-17 09:22:11 +01:00
|
|
|
if ( policyVertical == Qt::ScrollBarAlwaysOn )
|
|
|
|
orientations |= Qt::Vertical;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2018-11-17 09:22:11 +01:00
|
|
|
return orientations;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#include "moc_QskScrollView.cpp"
|