Using a flat map ( sorted std::vector ) instead of a std:map for the

animators. Preperations for inntroducing aspect/index as lookup key.
This commit is contained in:
Uwe Rathmann 2022-09-12 18:18:51 +02:00
parent a4a6e28ecc
commit 1900adbabb
2 changed files with 103 additions and 37 deletions

View File

@ -12,7 +12,6 @@
#include <qthread.h> #include <qthread.h>
#include <algorithm> #include <algorithm>
#include <map>
#include <vector> #include <vector>
#define ALIGN_VALUES 0 #define ALIGN_VALUES 0
@ -93,7 +92,8 @@ static inline bool qskCheckReceiverThread( const QObject* receiver )
return ( thread == QThread::currentThread() ); return ( thread == QThread::currentThread() );
} }
QskHintAnimator::QskHintAnimator() noexcept QskHintAnimator::QskHintAnimator( const QskAspect aspect ) noexcept
: m_aspect( aspect )
{ {
} }
@ -101,7 +101,7 @@ QskHintAnimator::~QskHintAnimator()
{ {
} }
void QskHintAnimator::setAspect( QskAspect aspect ) noexcept void QskHintAnimator::setAspect( const QskAspect aspect ) noexcept
{ {
m_aspect = aspect; m_aspect = aspect;
} }
@ -154,8 +154,69 @@ void QskHintAnimator::advance( qreal progress )
} }
} }
#ifndef QT_NO_DEBUG_STREAM
#include <qdebug.h>
QDebug operator<<( QDebug debug, const QskHintAnimator& animator )
{
QDebugStateSaver saver( debug );
debug.nospace();
debug << "Animator" << "( ";
debug << animator.aspect() << ", " << animator.endValue().typeName() << ", ";
if ( animator.isRunning() )
debug << "R: " << animator.duration() << ", " << animator.elapsed();
else
debug << "S" << animator.duration();
if ( auto control = animator.control() )
debug << ", " << control->className() << ", " << (void*) control;
debug << " )";
return debug;
}
#endif
namespace namespace
{ {
class AnimatorMap : public std::vector< QskHintAnimator* >
{
public:
~AnimatorMap()
{
qDeleteAll( *this );
}
inline const QskHintAnimator* find( const QskAspect aspect ) const
{
auto it = std::lower_bound( cbegin(), cend(), aspect, lessThan );
if ( it != cend() && (*it)->aspect() == aspect )
return *it;
return nullptr;
}
inline QskHintAnimator* findOrInsert( const QskAspect aspect )
{
auto it = std::lower_bound( begin(), end(), aspect, lessThan );
if ( it == end() || (*it)->aspect() != aspect )
it = insert( it, new QskHintAnimator( aspect ) );
return *it;
}
private:
static inline bool lessThan( const QskHintAnimator* animator, const QskAspect& aspect )
{
return animator->aspect() < aspect;
}
};
class AnimatorGuard final : public QObject class AnimatorGuard final : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -204,8 +265,7 @@ namespace
class QskHintAnimatorTable::PrivateData class QskHintAnimatorTable::PrivateData
{ {
public: public:
// we could use a std::set< QskHintAnimator > instead AnimatorMap animators; // a flat map
std::map< QskAspect, QskHintAnimator > map;
}; };
QskHintAnimatorTable::QskHintAnimatorTable() QskHintAnimatorTable::QskHintAnimatorTable()
@ -232,20 +292,19 @@ void QskHintAnimatorTable::start( QskControl* control,
qskAnimatorGuard->registerTable( this ); qskAnimatorGuard->registerTable( this );
} }
auto& animator = m_data->map[ aspect ]; auto animator = m_data->animators.findOrInsert( aspect );
animator.setAspect( aspect ); animator->setStartValue( from );
animator.setStartValue( from ); animator->setEndValue( to );
animator.setEndValue( to );
animator.setDuration( animationHint.duration ); animator->setDuration( animationHint.duration );
animator.setEasingCurve( animationHint.type ); animator->setEasingCurve( animationHint.type );
animator.setUpdateFlags( animationHint.updateFlags ); animator->setUpdateFlags( animationHint.updateFlags );
animator.setControl( control ); animator->setControl( control );
animator.setWindow( control->window() ); animator->setWindow( control->window() );
animator.start(); animator->start();
if ( qskCheckReceiverThread( control ) ) if ( qskCheckReceiverThread( control ) )
{ {
@ -256,26 +315,20 @@ void QskHintAnimatorTable::start( QskControl* control,
const QskHintAnimator* QskHintAnimatorTable::animator( QskAspect aspect ) const const QskHintAnimator* QskHintAnimatorTable::animator( QskAspect aspect ) const
{ {
if ( m_data == nullptr ) if ( m_data )
return nullptr; return m_data->animators.find( aspect );
auto it = m_data->map.find( aspect ); return nullptr;
if ( it == m_data->map.end() )
return nullptr;
return &( it->second );
} }
QVariant QskHintAnimatorTable::currentValue( QskAspect aspect ) const QVariant QskHintAnimatorTable::currentValue( QskAspect aspect ) const
{ {
if ( m_data ) if ( m_data )
{ {
const auto it = m_data->map.find( aspect ); if ( auto animator = m_data->animators.find( aspect ) )
if ( it != m_data->map.cend() )
{ {
const auto& animator = it->second; if ( animator->isRunning() )
if ( animator.isRunning() ) return animator->currentValue();
return animator.currentValue();
} }
} }
@ -287,15 +340,21 @@ bool QskHintAnimatorTable::cleanup()
if ( m_data == nullptr ) if ( m_data == nullptr )
return true; return true;
for ( auto it = m_data->map.begin(); it != m_data->map.end(); ) auto &animators = m_data->animators;
{
// remove all terminated animators
if ( !it->second.isRunning() )
{
auto control = it->second.control();
auto aspect = it->first;
it = m_data->map.erase( it ); for ( auto it = animators.begin(); it != animators.end(); )
{
auto animator = *it;
// remove all terminated animators
if ( !animator->isRunning() )
{
const auto control = animator->control();
const auto aspect = animator->aspect();
delete animator;
it = animators.erase( it );
if ( control ) if ( control )
{ {
@ -312,7 +371,7 @@ bool QskHintAnimatorTable::cleanup()
} }
} }
if ( m_data->map.empty() ) if ( animators.empty() )
{ {
delete m_data; delete m_data;
m_data = nullptr; m_data = nullptr;

View File

@ -19,7 +19,7 @@ class QSK_EXPORT QskHintAnimator : public QskVariantAnimator
using Inherited = QskVariantAnimator; using Inherited = QskVariantAnimator;
public: public:
QskHintAnimator() noexcept; QskHintAnimator( QskAspect = QskAspect() ) noexcept;
~QskHintAnimator() override; ~QskHintAnimator() override;
void setAspect( QskAspect ) noexcept; void setAspect( QskAspect ) noexcept;
@ -41,6 +41,13 @@ class QSK_EXPORT QskHintAnimator : public QskVariantAnimator
QPointer< QskControl > m_control; QPointer< QskControl > m_control;
}; };
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
QSK_EXPORT QDebug operator<<( QDebug, const QskHintAnimator& );
#endif
class QSK_EXPORT QskHintAnimatorTable class QSK_EXPORT QskHintAnimatorTable
{ {
public: public: