qskinny/src/controls/QskPageIndicator.cpp

257 lines
5.7 KiB
C++
Raw Normal View History

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 "QskPageIndicator.h"
2022-01-04 15:58:49 +01:00
#include "QskSkinlet.h"
#include "QskEvent.h"
2017-07-21 18:21:34 +02:00
QSK_SUBCONTROL( QskPageIndicator, Panel )
QSK_SUBCONTROL( QskPageIndicator, Bullet )
2022-01-04 13:58:34 +01:00
QSK_SYSTEM_STATE( QskPageIndicator, Selected, QskAspect::FirstSystemState << 1 )
2017-07-21 18:21:34 +02:00
2022-01-04 15:58:49 +01:00
static int qskKeyIncrement(
const QskPageIndicator* indicator, const QKeyEvent* event )
{
2022-03-11 14:24:10 +01:00
if ( qskIsStandardKeyInput( event, QKeySequence::MoveToNextChar ) )
2022-01-04 15:58:49 +01:00
return 1;
2022-03-11 14:24:10 +01:00
if ( qskIsStandardKeyInput( event, QKeySequence::MoveToPreviousChar ) )
2022-01-04 15:58:49 +01:00
return -1;
const auto key = event->key();
if ( indicator->orientation() == Qt::Horizontal )
{
const bool mirrored = indicator->layoutMirroring();
if ( key == Qt::Key_Left )
return mirrored ? 1 : -1;
2022-03-23 11:54:34 +01:00
2022-01-04 15:58:49 +01:00
if ( key == Qt::Key_Right )
return mirrored ? -1 : 1;
2022-03-23 11:54:34 +01:00
}
2022-01-04 15:58:49 +01:00
else
{
if ( key == Qt::Key_Up )
return -1;
if ( key == Qt::Key_Down )
return 1;
2022-03-23 11:54:34 +01:00
}
2022-01-04 15:58:49 +01:00
return 0;
2022-03-23 11:54:34 +01:00
}
2022-01-04 15:58:49 +01:00
2017-07-21 18:21:34 +02:00
class QskPageIndicator::PrivateData
{
2018-08-03 08:15:28 +02:00
public:
PrivateData( int count )
: count( count )
, orientation( Qt::Horizontal )
2017-07-21 18:21:34 +02:00
{
}
2022-01-04 13:58:34 +01:00
qreal currentIndex = -1;
2022-01-04 15:58:49 +01:00
int pressedIndex = -1;
2022-01-04 13:58:34 +01:00
2017-07-21 18:21:34 +02:00
int count;
Qt::Orientation orientation : 2;
};
2018-08-03 08:15:28 +02:00
QskPageIndicator::QskPageIndicator( int count, QQuickItem* parent )
: Inherited( parent )
, m_data( new PrivateData( count ) )
2017-07-21 18:21:34 +02:00
{
// as we don't stretch the bullets
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
2017-07-21 18:21:34 +02:00
}
2018-08-03 08:15:28 +02:00
QskPageIndicator::QskPageIndicator( QQuickItem* parent )
: QskPageIndicator( 0, parent )
2017-07-21 18:21:34 +02:00
{
}
QskPageIndicator::~QskPageIndicator()
{
}
int QskPageIndicator::count() const
{
return m_data->count;
}
qreal QskPageIndicator::currentIndex() const
{
return m_data->currentIndex;
}
Qt::Orientation QskPageIndicator::orientation() const
{
return m_data->orientation;
}
void QskPageIndicator::setOrientation( Qt::Orientation orientation )
{
2018-08-03 08:15:28 +02:00
if ( orientation != m_data->orientation )
2017-07-21 18:21:34 +02:00
{
m_data->orientation = orientation;
resetImplicitSize();
update();
2020-12-17 16:14:56 +01:00
Q_EMIT orientationChanged( orientation );
2017-07-21 18:21:34 +02:00
}
}
void QskPageIndicator::setCount( int count )
{
if ( count != m_data->count )
{
m_data->count = count;
resetImplicitSize();
update();
2020-12-17 16:14:56 +01:00
Q_EMIT countChanged( count );
2017-07-21 18:21:34 +02:00
}
}
void QskPageIndicator::setCurrentIndex( qreal index )
{
if ( index < 0 || index >= m_data->count )
index = -1;
2018-08-03 08:15:28 +02:00
if ( index != m_data->currentIndex )
2017-07-21 18:21:34 +02:00
{
m_data->currentIndex = index;
update();
2020-12-17 16:14:56 +01:00
Q_EMIT currentIndexChanged( index );
2017-07-21 18:21:34 +02:00
}
}
2022-01-04 13:58:34 +01:00
qreal QskPageIndicator::valueRatioAt( int index ) const
{
if ( m_data->currentIndex >= 0.0 && index >= 0 )
{
qreal pos = m_data->currentIndex;
if ( index == 0 && pos > m_data->count - 1 )
pos -= m_data->count;
const qreal diff = 1.0 - std::abs( pos - index );
return std::max( diff, 0.0 );
2022-03-23 11:54:34 +01:00
}
2022-01-04 13:58:34 +01:00
return 0.0;
}
2022-01-04 15:58:49 +01:00
QRectF QskPageIndicator::bulletRect( int index ) const
{
return effectiveSkinlet()->sampleRect(
this, contentsRect(), QskPageIndicator::Bullet, index );
}
int QskPageIndicator::indexAtPosition( const QPointF& pos ) const
{
return effectiveSkinlet()->sampleIndexAt(
this, contentsRect(), QskPageIndicator::Bullet, pos );
}
2022-01-04 14:34:15 +01:00
QskAspect::Placement QskPageIndicator::effectivePlacement() const
{
return static_cast< QskAspect::Placement >( m_data->orientation );
}
2022-01-04 15:58:49 +01:00
void QskPageIndicator::mousePressEvent( QMouseEvent* event )
{
if ( event->button() == Qt::LeftButton )
{
2022-01-05 11:59:32 +01:00
/*
The bullets are usually small and therefore hard to click - with
touch input almost impossible. It might be better to
increment in direction of the mouse position ?
A swipe gesture might make more sense, TODO ...
*/
2022-01-04 15:58:49 +01:00
const auto pos = qskMousePosition( event );
m_data->pressedIndex = indexAtPosition( pos );
return;
}
2022-03-24 17:10:11 +01:00
Inherited::mousePressEvent( event );
2022-01-04 15:58:49 +01:00
}
2022-01-05 11:59:32 +01:00
void QskPageIndicator::mouseUngrabEvent()
{
m_data->pressedIndex = -1;
}
2022-01-04 15:58:49 +01:00
void QskPageIndicator::mouseReleaseEvent( QMouseEvent* event )
{
if ( event->button() == Qt::LeftButton )
{
const auto index = m_data->pressedIndex;
m_data->pressedIndex = -1;
if ( index >= 0 )
{
const auto pos = qskMousePosition( event );
if ( indexAtPosition( pos ) == index )
Q_EMIT pageRequested( index );
}
2022-03-23 11:54:34 +01:00
2022-01-04 15:58:49 +01:00
return;
}
2022-03-24 17:10:11 +01:00
Inherited::mouseReleaseEvent( event );
2022-01-04 15:58:49 +01:00
}
void QskPageIndicator::keyPressEvent( QKeyEvent* event )
{
if ( const int increment = qskKeyIncrement( this, event ) )
{
2022-01-05 11:59:32 +01:00
incrementRequested( increment );
2022-01-04 15:58:49 +01:00
return;
}
Inherited::keyPressEvent( event );
}
2022-01-05 11:59:32 +01:00
#ifndef QT_NO_WHEELEVENT
2022-01-04 15:58:49 +01:00
void QskPageIndicator::wheelEvent( QWheelEvent* event )
{
2022-01-05 11:59:32 +01:00
incrementRequested( qskWheelSteps( event ) );
}
2022-01-04 15:58:49 +01:00
#endif
2022-01-05 11:59:32 +01:00
void QskPageIndicator::incrementRequested( int offset )
{
const auto n = m_data->count;
if ( offset == 0 || n == 0 )
return;
int index = m_data->currentIndex;
if ( index < 0 && offset < 0 )
index = n;
// do we need a cycling on/off attribute, TODO ...
index = ( index + offset ) % n;
if ( index < 0 )
index += n;
if ( index != m_data->currentIndex )
Q_EMIT pageRequested( index );
2022-01-04 15:58:49 +01:00
}
2017-07-21 18:21:34 +02:00
#include "moc_QskPageIndicator.cpp"