/****************************************************************************** * QSkinny - Copyright (C) 2016 Uwe Rathmann * This file may be used under the terms of the QSkinny License, Version 1.0 *****************************************************************************/ #include "QskPageIndicatorSkinlet.h" #include "QskPageIndicator.h" #include "QskBoxNode.h" #include "QskSGNode.h" #include "QskFunctions.h" static inline int qskCurrentIndex( const QskPageIndicator* indicator ) { int index = qRound( indicator->currentIndex() ); if ( index >= indicator->count() ) index = 0; return index; } static QRectF qskBulletRect( const QskPageIndicator* indicator, const QRectF& rect, int index ) { using Q = QskPageIndicator; /* The bullets might have different sizes, but as a pager indicator usually does not have many bullets we can simply iterate */ const qreal spacing = indicator->spacingHint( Q::Panel ); const auto size = indicator->strutSizeHint( Q::Bullet ); qreal x = rect.x(); qreal y = rect.y(); if ( indicator->orientation() == Qt::Horizontal ) { for ( int i = 0; i < index; i++ ) x += size.width() + spacing; y += 0.5 * ( rect.height() - size.height() ); } else { for ( int i = 0; i < index; i++ ) y += size.height() + spacing; x += 0.5 * ( rect.width() - size.width() ); } return QRectF( x, y, size.width(), size.height() ); } QskPageIndicatorSkinlet::QskPageIndicatorSkinlet( QskSkin* skin ) : QskSkinlet( skin ) { setNodeRoles( { PanelRole, BulletsRole } ); } QskPageIndicatorSkinlet::~QskPageIndicatorSkinlet() { } QRectF QskPageIndicatorSkinlet::subControlRect( const QskSkinnable* skinnable, const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const { if ( subControl == QskPageIndicator::Panel ) return contentsRect; return Inherited::subControlRect( skinnable, contentsRect, subControl ); } QSGNode* QskPageIndicatorSkinlet::updateSubNode( const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const { using Q = QskPageIndicator; switch ( nodeRole ) { case PanelRole: return updateBoxNode( skinnable, node, Q::Panel ); case BulletsRole: return updateSeriesNode( skinnable, Q::Bullet, node ); } return Inherited::updateSubNode( skinnable, nodeRole, node ); } int QskPageIndicatorSkinlet::sampleCount( const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) const { using Q = QskPageIndicator; if ( subControl == Q::Bullet ) { const auto indicator = static_cast< const QskPageIndicator* >( skinnable ); return indicator->count(); } return Inherited::sampleCount( skinnable, subControl ); } QRectF QskPageIndicatorSkinlet::sampleRect( const QskSkinnable* skinnable, const QRectF& contentsRect, QskAspect::Subcontrol subControl, int index ) const { using Q = QskPageIndicator; if ( subControl == Q::Bullet ) { const auto indicator = static_cast< const QskPageIndicator* >( skinnable ); const auto rect = indicator->subControlContentsRect( Q::Panel ); return qskBulletRect( indicator, rect, index ); } return Inherited::sampleRect( skinnable, contentsRect, subControl, index ); } int QskPageIndicatorSkinlet::sampleIndexAt( const QskSkinnable* skinnable, const QRectF& contentsRect, QskAspect::Subcontrol subControl, const QPointF& pos ) const { // TODO ... return Inherited::sampleIndexAt( skinnable, contentsRect, subControl, pos ); } QSGNode* QskPageIndicatorSkinlet::updateSampleNode( const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index, QSGNode* node ) const { using Q = QskPageIndicator; if ( subControl == Q::Bullet ) { auto indicator = static_cast< const QskPageIndicator* >( skinnable ); const auto rect = sampleRect( indicator, indicator->contentsRect(), Q::Bullet, index ); const auto ratio = indicator->valueRatioAt( index ); return QskSkinlet::updateInterpolatedBoxNode( skinnable, node, rect, Q::Bullet, Q::Bullet | Q::Selected, ratio ); } return nullptr; } QSizeF QskPageIndicatorSkinlet::sizeHint( const QskSkinnable* skinnable, Qt::SizeHint which, const QSizeF& ) const { using Q = QskPageIndicator; if ( which != Qt::PreferredSize ) return QSizeF(); const auto indicator = static_cast< const QskPageIndicator* >( skinnable ); QSizeF size( 0.0, 0.0 ); const int n = indicator->count(); if ( n > 0 ) { size = indicator->strutSizeHint( Q::Bullet ); const qreal spacing = indicator->spacingHint( Q::Panel ); if ( indicator->orientation() == Qt::Horizontal ) size.rwidth() += ( n - 1 ) * ( size.width() + spacing ); else size.rheight() += ( n - 1 ) * ( size.height() + spacing ); } const auto hint = indicator->outerBoxSize( Q::Panel, size ); return hint.expandedTo( indicator->strutSizeHint( Q::Panel ) ); } #include "moc_QskPageIndicatorSkinlet.cpp"