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 "QskPageIndicatorSkinlet.h"
|
2018-08-03 08:15:28 +02:00
|
|
|
#include "QskPageIndicator.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2018-08-03 08:30:23 +02:00
|
|
|
#include "QskBoxNode.h"
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskPageIndicatorSkinlet::QskPageIndicatorSkinlet( QskSkin* skin )
|
|
|
|
: QskSkinlet( skin )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
setNodeRoles( { PanelRole, BulletsRole } );
|
|
|
|
}
|
|
|
|
|
|
|
|
QskPageIndicatorSkinlet::~QskPageIndicatorSkinlet()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-04-25 14:23:39 +02:00
|
|
|
QRectF QskPageIndicatorSkinlet::subControlRect( const QskSkinnable* skinnable,
|
|
|
|
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
if ( subControl == QskPageIndicator::Panel )
|
|
|
|
{
|
2019-04-25 14:23:39 +02:00
|
|
|
return contentsRect;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2019-04-25 14:23:39 +02:00
|
|
|
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QSGNode* QskPageIndicatorSkinlet::updateSubNode(
|
|
|
|
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
2017-09-01 11:55:55 +02:00
|
|
|
{
|
|
|
|
const auto indicator = static_cast< const QskPageIndicator* >( skinnable );
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
switch ( nodeRole )
|
2017-09-01 11:55:55 +02:00
|
|
|
{
|
|
|
|
case PanelRole:
|
|
|
|
{
|
|
|
|
return updateBoxNode( indicator, node, QskPageIndicator::Panel );
|
|
|
|
}
|
|
|
|
|
|
|
|
case BulletsRole:
|
|
|
|
{
|
|
|
|
return updateBulletsNode( indicator, node );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
QRectF QskPageIndicatorSkinlet::bulletRect(
|
|
|
|
const QskPageIndicator* indicator, const QRectF& rect, int index ) const
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
const qreal szNormal =
|
|
|
|
indicator->metric( QskPageIndicator::Bullet | QskAspect::Size );
|
|
|
|
|
|
|
|
const qreal szHighlighted =
|
|
|
|
indicator->metric( QskPageIndicator::Highlighted | QskAspect::Size );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
// scale bullet size if we are in between a transition:
|
|
|
|
qreal indexDiff = qAbs( indicator->currentIndex() - index );
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( indexDiff > ( indicator->count() - 1 ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
indexDiff = ( indicator->count() - indicator->currentIndex() ); // wrapping
|
|
|
|
|
2019-01-04 13:42:16 +01:00
|
|
|
const qreal sz = ( indexDiff < 1 ) ?
|
2017-07-21 18:21:34 +02:00
|
|
|
( 1 - indexDiff ) * szHighlighted + indexDiff * szNormal : szNormal;
|
|
|
|
|
|
|
|
const qreal spacing = indicator->metric( QskPageIndicator::Panel | QskAspect::Spacing );
|
|
|
|
const bool horizontal = ( indicator->orientation() == Qt::Horizontal );
|
|
|
|
|
|
|
|
qreal w, h;
|
|
|
|
if ( horizontal )
|
|
|
|
{
|
|
|
|
w = ( indicator->count() - 1 ) * ( szNormal + spacing ) + szHighlighted;
|
|
|
|
h = rect.height();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
w = rect.width();
|
|
|
|
h = ( indicator->count() - 1 ) * ( szNormal + spacing ) + szHighlighted;
|
|
|
|
}
|
2017-09-01 13:09:24 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
QRectF r( 0, 0, w, h );
|
|
|
|
r.moveCenter( rect.center() );
|
|
|
|
|
|
|
|
const qreal s = ( index > indicator->currentIndex() ) ? szHighlighted : szNormal;
|
|
|
|
|
|
|
|
qreal s2;
|
|
|
|
if ( indexDiff < 1 && index >= indicator->currentIndex() )
|
|
|
|
{
|
2017-09-01 13:09:24 +02:00
|
|
|
// scrolling from or to this bullet:
|
2017-07-21 18:21:34 +02:00
|
|
|
s2 = szNormal + qAbs( szHighlighted - szNormal ) * indexDiff;
|
|
|
|
}
|
|
|
|
else if ( ( indicator->currentIndex() > ( indicator->count() - 1 ) &&
|
2018-08-03 08:15:28 +02:00
|
|
|
index > ( indicator->currentIndex() - indicator->count() + 1 ) ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-09-01 13:09:24 +02:00
|
|
|
// wrapping case:
|
2017-07-21 18:21:34 +02:00
|
|
|
qreal wrappingDiff = indexDiff;
|
|
|
|
while ( wrappingDiff > 1 )
|
|
|
|
wrappingDiff -= 1;
|
|
|
|
s2 = szNormal + qAbs( szHighlighted - szNormal ) * wrappingDiff;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s2 = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal x = r.left() + s2 + spacing + ( index - 1 ) * ( szNormal + spacing );
|
|
|
|
|
|
|
|
qreal yAdjust;
|
|
|
|
if ( indicator->currentIndex() == index )
|
|
|
|
{
|
|
|
|
yAdjust = qMax( 0.0, szNormal - szHighlighted ) / 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
yAdjust = qMax( 0.0, szHighlighted - szNormal ) / 2;
|
|
|
|
}
|
|
|
|
if ( indexDiff < 1 )
|
|
|
|
yAdjust *= indexDiff;
|
|
|
|
const qreal y = ( horizontal ? r.top() : r.left() ) + yAdjust;
|
|
|
|
|
|
|
|
QRectF ret = horizontal ? QRectF( x, y, sz, sz ) : QRectF( y, x, sz, sz );
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
QSGNode* QskPageIndicatorSkinlet::updateBulletsNode(
|
2018-08-03 08:15:28 +02:00
|
|
|
const QskPageIndicator* indicator, QSGNode* node ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
if ( indicator->count() == 0 )
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if ( node == nullptr )
|
|
|
|
node = new QSGNode();
|
|
|
|
|
2019-04-25 14:23:39 +02:00
|
|
|
QRectF rect = indicator->subControlRect( QskPageIndicator::Panel );
|
2017-07-21 18:21:34 +02:00
|
|
|
rect = indicator->innerBox( QskPageIndicator::Panel, rect );
|
|
|
|
|
|
|
|
// index of the highlighted bullet
|
|
|
|
int currentBullet = qRound( indicator->currentIndex() );
|
|
|
|
if ( currentBullet >= indicator->count() )
|
|
|
|
currentBullet = 0;
|
|
|
|
|
|
|
|
auto bulletNode = node->firstChild();
|
|
|
|
for ( int i = 0; i < indicator->count(); i++ )
|
|
|
|
{
|
|
|
|
using Q = QskPageIndicator;
|
|
|
|
|
|
|
|
if ( i > 0 )
|
|
|
|
bulletNode = bulletNode->nextSibling();
|
|
|
|
|
|
|
|
if ( bulletNode == nullptr )
|
|
|
|
bulletNode = new QskBoxNode();
|
|
|
|
|
|
|
|
updateBoxNode( indicator, bulletNode, bulletRect( indicator, rect, i ),
|
|
|
|
( i == currentBullet ) ? Q::Highlighted : Q::Bullet );
|
2017-10-17 17:34:00 +02:00
|
|
|
|
|
|
|
if ( bulletNode->parent() != node )
|
|
|
|
node->appendChildNode( bulletNode );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// if count has decreased we need to remove superfluous nodes
|
2020-07-23 09:29:45 +02:00
|
|
|
removeTraillingNodes( node, bulletNode );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "moc_QskPageIndicatorSkinlet.cpp"
|