181 lines
5.4 KiB
C++
181 lines
5.4 KiB
C++
/******************************************************************************
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*****************************************************************************/
|
|
|
|
#include "QskPageIndicatorSkinlet.h"
|
|
#include "QskPageIndicator.h"
|
|
|
|
#include "QskSGNode.h"
|
|
#include "QskFunctions.h"
|
|
|
|
static QRectF qskBulletRect( const QskPageIndicator* indicator,
|
|
const QRectF& rect, int index )
|
|
{
|
|
using Q = QskPageIndicator;
|
|
|
|
const auto n = indicator->count();
|
|
if ( n <= 0 || index < 0 || index >= n )
|
|
return QRectF();
|
|
|
|
if ( indicator->layoutMirroring() )
|
|
{
|
|
if ( indicator->orientation() == Qt::Horizontal )
|
|
index = n - ( index + 1 );
|
|
}
|
|
|
|
const auto size = indicator->strutSizeHint( Q::Bullet );
|
|
const qreal spacing = indicator->spacingHint( Q::Panel );
|
|
const auto alignment = indicator->alignmentHint( Q::Panel, Qt::AlignCenter );
|
|
|
|
qreal x, y;
|
|
|
|
if ( indicator->orientation() == Qt::Horizontal )
|
|
{
|
|
const auto maxWidth = n * size.width() + ( n - 1 ) * spacing;
|
|
const auto r = qskAlignedRectF( rect, maxWidth, size.height(), alignment );
|
|
|
|
x = r.x() + index * ( size.width() + spacing );
|
|
y = r.y();
|
|
}
|
|
else
|
|
{
|
|
const auto maxHeight = n * size.height() + ( n - 1 ) * spacing;
|
|
const auto r = qskAlignedRectF( rect, maxHeight, size.height(), alignment );
|
|
|
|
x = r.x();
|
|
y = r.y() + index * ( size.height() + spacing );;
|
|
}
|
|
|
|
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 );
|
|
|
|
/*
|
|
QskSkinnable::effectiveSkinHint() does not add the skinStates(), when
|
|
the aspect already has a state. So we need add thmen here.
|
|
*/
|
|
const auto selectedStates = Q::Selected | indicator->skinStates();
|
|
|
|
return QskSkinlet::updateInterpolatedBoxNode( skinnable, node,
|
|
rect, Q::Bullet, Q::Bullet | selectedStates, 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"
|