6#include "QskScrollView.h"
7#include "QskAnimationHint.h"
8#include "QskBoxBorderMetrics.h"
20static inline
QskAspect::Subcontrol qskSubControlAt(
29 for (
auto subControl : { Q::VerticalScrollHandle, Q::VerticalScrollBar,
30 Q::HorizontalScrollHandle, Q::HorizontalScrollBar } )
32 if ( scrollView->subControlRect( rect, subControl ).contains( pos ) )
36 return QskAspect::NoSubcontrol;
39class QskScrollView::PrivateData
44 setScrolling( scrollView, QskAspect::NoSubcontrol, 0.0 );
50 if ( subControl == pressedSubControl )
54 if ( subControl == VerticalScrollHandle || pressedSubControl == VerticalScrollHandle )
65 pressedSubControl = subControl;
70 auto oldStates = scrollView->skinStates() | scrollView->scrollBarStates( subControl );
71 auto newStates = oldStates | QskScrollView::Pressed;
73 if ( pressedSubControl == QskAspect::NoSubcontrol )
74 qSwap( oldStates, newStates );
76 scrollView->startHintTransitions( {
subControls[0] }, oldStates, newStates );
77 scrollView->startHintTransitions( {
subControls[1] }, oldStates, newStates );
82 if ( subControl == this->hoveredSubControl )
86 if ( subControl == VerticalScrollHandle
87 || hoveredSubControl == VerticalScrollHandle
88 || subControl == VerticalScrollBar
89 || hoveredSubControl == VerticalScrollBar )
102 hoveredSubControl = subControl;
104 auto oldStates = scrollView->skinStates();
107 if ( hoveredSubControl == QskAspect::NoSubcontrol )
108 qSwap( oldStates, newStates );
110 scrollView->startHintTransitions( {
subControls[0] }, oldStates, newStates );
113 scrollView->startHintTransitions( {
subControls[1] }, oldStates, newStates );
118 if ( subControl == QskAspect::NoSubcontrol )
121 const auto stateSubcontrol =
124 if ( subControl == stateSubcontrol )
128 if ( subControl == VerticalScrollBar )
129 return stateSubcontrol == VerticalScrollHandle;
131 if ( subControl == HorizontalScrollBar )
132 return stateSubcontrol == HorizontalScrollHandle;
137 Qt::ScrollBarPolicy horizontalScrollBarPolicy = Qt::ScrollBarAsNeeded;
138 Qt::ScrollBarPolicy verticalScrollBarPolicy = Qt::ScrollBarAsNeeded;
140 qreal scrollPressPos = 0.0;
146QskScrollView::QskScrollView( QQuickItem* parent )
147 : Inherited( parent )
148 , m_data( new PrivateData() )
150 setAcceptHoverEvents(
true );
153QskScrollView::~QskScrollView()
163void QskScrollView::setVerticalScrollBarPolicy( Qt::ScrollBarPolicy policy )
165 if ( policy != m_data->verticalScrollBarPolicy )
167 m_data->verticalScrollBarPolicy = policy;
170 Q_EMIT verticalScrollBarPolicyChanged();
174Qt::ScrollBarPolicy QskScrollView::verticalScrollBarPolicy()
const
176 return m_data->verticalScrollBarPolicy;
179void QskScrollView::setHorizontalScrollBarPolicy( Qt::ScrollBarPolicy policy )
181 if ( policy != m_data->horizontalScrollBarPolicy )
183 m_data->horizontalScrollBarPolicy = policy;
186 Q_EMIT horizontalScrollBarPolicyChanged();
190Qt::ScrollBarPolicy QskScrollView::horizontalScrollBarPolicy()
const
192 return m_data->horizontalScrollBarPolicy;
195bool QskScrollView::isScrolling( Qt::Orientation orientation )
const
197 if ( orientation == Qt::Vertical )
198 return m_data->pressedSubControl == VerticalScrollHandle;
200 return m_data->pressedSubControl == HorizontalScrollHandle;
203QskAspect::States QskScrollView::scrollBarStates(
206 auto states = skinStates();
208 if ( m_data->hasState( subControl, Pressed ) )
211 if ( m_data->hasState( subControl,
Hovered ) )
217QRectF QskScrollView::viewContentsRect()
const
222 return r.marginsRemoved( borderMetrics.widths() );
225void QskScrollView::mousePressEvent( QMouseEvent* event )
227 const auto mousePos = qskMousePosition( event );
233 if ( handleRect.contains( mousePos ) )
235 m_data->setScrolling(
this, VerticalScrollHandle, mousePos.y() );
239 const QRectF vRect = viewContentsRect();
241 qreal y = scrollPos().y();
243 if ( mousePos.y() < handleRect.top() )
248 setScrollPos( QPointF( scrollPos().x(), y ) );
256 const QRectF handleRect =
subControlRect( HorizontalScrollHandle );
258 if ( handleRect.contains( mousePos ) )
260 m_data->setScrolling(
this, HorizontalScrollHandle, mousePos.x() );
264 const QRectF vRect = viewContentsRect();
266 qreal x = scrollPos().x();
268 if ( mousePos.x() < handleRect.left() )
273 setScrollPos( QPointF( x, scrollPos().y() ) );
279 Inherited::mousePressEvent( event );
282void QskScrollView::mouseMoveEvent( QMouseEvent* event )
284 if ( m_data->pressedSubControl == QskAspect::NoSubcontrol )
286 Inherited::mouseMoveEvent( event );
290 const auto mousePos = qskMousePosition( event );
291 QPointF pos = scrollPos();
293 if ( m_data->pressedSubControl == HorizontalScrollHandle )
295 const qreal dx = mousePos.x() - m_data->scrollPressPos;
298 pos.rx() += dx / w * scrollableSize().width();
299 m_data->scrollPressPos = mousePos.x();
303 const qreal dy = mousePos.y() - m_data->scrollPressPos;
306 pos.ry() += dy / h * scrollableSize().height();
307 m_data->scrollPressPos = mousePos.y();
310 if ( pos != scrollPos() )
314void QskScrollView::mouseReleaseEvent( QMouseEvent* event )
316 if ( m_data->pressedSubControl == QskAspect::NoSubcontrol )
318 Inherited::mouseReleaseEvent( event );
322 m_data->resetScrolling(
this );
325void QskScrollView::mouseUngrabEvent()
327 m_data->resetScrolling(
this );
330void QskScrollView::hoverEnterEvent( QHoverEvent* event )
332 const auto subControl = qskSubControlAt(
this, qskHoverPosition( event ) );
333 m_data->setHovered(
this, subControl );
336void QskScrollView::hoverMoveEvent( QHoverEvent* event )
338 const auto subControl = qskSubControlAt(
this, qskHoverPosition( event ) );
339 m_data->setHovered(
this, subControl );
342void QskScrollView::hoverLeaveEvent( QHoverEvent* )
344 m_data->setHovered(
this, QskAspect::NoSubcontrol );
347#ifndef QT_NO_WHEELEVENT
349QPointF QskScrollView::scrollOffset(
const QWheelEvent* event )
const
353 const auto pos = qskWheelPosition( event );
354 const auto viewRect = viewContentsRect();
358 const auto steps = qskWheelSteps( event );
359 offset.setY( steps );
363 const auto steps = qskWheelSteps( event );
364 offset.setX( steps );
366 else if ( viewRect.contains( pos ) )
368 offset =
event->pixelDelta();
369 if ( offset.isNull() )
370 offset =
event->angleDelta() / QWheelEvent::DefaultDeltasPerStep;
373 if ( !offset.isNull() )
375 const auto vs = viewRect.size() / 3.0;
377 offset.rx() *= vs.width();
378 offset.ry() *= vs.height();
386Qt::Orientations QskScrollView::scrollableOrientations()
const
391 auto policyVertical = m_data->verticalScrollBarPolicy;
392 auto policyHorizontal = m_data->horizontalScrollBarPolicy;
394 if ( policyVertical == Qt::ScrollBarAsNeeded )
396 qreal height = vr.height();
398 if ( policyHorizontal == Qt::ScrollBarAlwaysOn )
401 if ( scrollableSize().height() > height )
402 policyVertical = Qt::ScrollBarAlwaysOn;
405 if ( policyHorizontal == Qt::ScrollBarAsNeeded )
407 qreal width = vr.width();
409 if ( policyVertical == Qt::ScrollBarAlwaysOn )
412 if ( scrollableSize().width() > width )
414 policyHorizontal = Qt::ScrollBarAlwaysOn;
418 if ( ( policyVertical == Qt::ScrollBarAsNeeded ) &&
419 ( scrollableSize().height() >
422 policyVertical = Qt::ScrollBarAlwaysOn;
427 Qt::Orientations orientations;
429 if ( policyHorizontal == Qt::ScrollBarAlwaysOn )
430 orientations |= Qt::Horizontal;
432 if ( policyVertical == Qt::ScrollBarAlwaysOn )
433 orientations |= Qt::Vertical;
438#include "moc_QskScrollView.cpp"
Lookup key for a QskSkinHintTable.
Subcontrol
For use within the rendering or lay-outing of a specific QskSkinnable.
QRectF subControlRect(QskAspect::Subcontrol) const
static const QskAspect::State Hovered
QRectF contentsRect() const
QVector< QskAspect::Subcontrol > subControls() const
QskAnimationHint effectiveAnimation(QskAspect::Type, QskAspect::Subcontrol, QskAspect::States, QskSkinHintStatus *status=nullptr) const
QskBoxBorderMetrics boxBorderMetricsHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a border hint.
qreal metric(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a metric hint.