index added for animator lookups to allow smooth transitions f.e when
selcting an cell in a list box
This commit is contained in:
parent
7ca1e2f261
commit
4f8a76234a
@ -482,6 +482,8 @@ void Editor::setupSegmentedBar()
|
||||
using A = QskAspect;
|
||||
using Q = QskSegmentedBar;
|
||||
|
||||
const uint duration = 100;
|
||||
|
||||
{
|
||||
// Panel
|
||||
|
||||
@ -521,7 +523,7 @@ void Editor::setupSegmentedBar()
|
||||
setGradient( Q::Cursor | Q::Disabled, QColor( Qt::gray ).darker( 110 ) );
|
||||
setBoxBorderColors( Q::Cursor | Q::Disabled, Qt::gray );
|
||||
|
||||
setAnimation( Q::Cursor | A::Metric | A::Position, 100 );
|
||||
setAnimation( Q::Cursor | A::Metric | A::Position, duration );
|
||||
}
|
||||
|
||||
for( auto subControl : { Q::Panel, Q::Cursor } )
|
||||
@ -537,6 +539,8 @@ void Editor::setupSegmentedBar()
|
||||
|
||||
for( auto state : { A::NoState, Q::Selected } )
|
||||
setColor( Q::Text | state | Q::Disabled, m_pal.darker200 );
|
||||
|
||||
setAnimation( Q::Text | A::Color, duration );
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -208,9 +208,10 @@ QskGestureEvent* QskGestureEvent::clone() const
|
||||
|
||||
// -- QskAnimatorEvent
|
||||
|
||||
QskAnimatorEvent::QskAnimatorEvent( QskAspect aspect, State state )
|
||||
QskAnimatorEvent::QskAnimatorEvent( QskAspect aspect, int index, State state )
|
||||
: QskEvent( QskEvent::Animator )
|
||||
, m_aspect( aspect )
|
||||
, m_index( index )
|
||||
, m_state( state )
|
||||
{
|
||||
}
|
||||
|
@ -143,9 +143,10 @@ class QSK_EXPORT QskAnimatorEvent : public QskEvent
|
||||
Terminated
|
||||
};
|
||||
|
||||
QskAnimatorEvent( QskAspect aspect, State state );
|
||||
QskAnimatorEvent( QskAspect aspect, int index, State state );
|
||||
|
||||
inline QskAspect aspect() const { return m_aspect; }
|
||||
inline int index() const { return m_index; }
|
||||
inline State state() const { return m_state; }
|
||||
|
||||
QskAnimatorEvent* clone() const override;
|
||||
@ -155,6 +156,7 @@ class QSK_EXPORT QskAnimatorEvent : public QskEvent
|
||||
|
||||
private:
|
||||
QskAspect m_aspect;
|
||||
int m_index;
|
||||
State m_state;
|
||||
};
|
||||
|
||||
|
@ -92,8 +92,9 @@ static inline bool qskCheckReceiverThread( const QObject* receiver )
|
||||
return ( thread == QThread::currentThread() );
|
||||
}
|
||||
|
||||
QskHintAnimator::QskHintAnimator( const QskAspect aspect ) noexcept
|
||||
QskHintAnimator::QskHintAnimator( const QskAspect aspect, int index ) noexcept
|
||||
: m_aspect( aspect )
|
||||
, m_index( index )
|
||||
{
|
||||
}
|
||||
|
||||
@ -106,6 +107,11 @@ void QskHintAnimator::setAspect( const QskAspect aspect ) noexcept
|
||||
m_aspect = aspect;
|
||||
}
|
||||
|
||||
void QskHintAnimator::setIndex( int index ) noexcept
|
||||
{
|
||||
m_index = index;
|
||||
}
|
||||
|
||||
void QskHintAnimator::setUpdateFlags( QskAnimationHint::UpdateFlags flags ) noexcept
|
||||
{
|
||||
m_updateFlags = flags;
|
||||
@ -167,11 +173,14 @@ QDebug operator<<( QDebug debug, const QskHintAnimator& animator )
|
||||
|
||||
debug << animator.aspect() << ", " << animator.endValue().typeName() << ", ";
|
||||
|
||||
if ( animator.index() >= 0 )
|
||||
debug << animator.index() << ", ";
|
||||
|
||||
if ( animator.isRunning() )
|
||||
debug << "R: " << animator.duration() << ", " << animator.elapsed();
|
||||
else
|
||||
debug << "S" << animator.duration();
|
||||
|
||||
|
||||
if ( auto control = animator.control() )
|
||||
debug << ", " << control->className() << ", " << (void*) control;
|
||||
|
||||
@ -192,28 +201,46 @@ namespace
|
||||
qDeleteAll( *this );
|
||||
}
|
||||
|
||||
inline const QskHintAnimator* find( const QskAspect aspect ) const
|
||||
inline const QskHintAnimator* find( const QskAspect aspect, int index ) const
|
||||
{
|
||||
auto it = std::lower_bound( cbegin(), cend(), aspect, lessThan );
|
||||
if ( it != cend() && (*it)->aspect() == aspect )
|
||||
return *it;
|
||||
const Key key { aspect, index };
|
||||
|
||||
auto it = std::lower_bound( cbegin(), cend(), key, lessThan );
|
||||
if ( it != cend() )
|
||||
{
|
||||
if ( ( ( *it )->aspect() == aspect ) && ( ( *it )->index() == index ) )
|
||||
return *it;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline QskHintAnimator* findOrInsert( const QskAspect aspect )
|
||||
inline QskHintAnimator* findOrInsert( const QskAspect aspect, int index )
|
||||
{
|
||||
auto it = std::lower_bound( begin(), end(), aspect, lessThan );
|
||||
if ( it == end() || (*it)->aspect() != aspect )
|
||||
it = insert( it, new QskHintAnimator( aspect ) );
|
||||
const Key key { aspect, index };
|
||||
|
||||
auto it = std::lower_bound( begin(), end(), key, lessThan );
|
||||
if ( it == end() || ( *it )->aspect() != aspect || ( *it )->index() != index )
|
||||
{
|
||||
it = insert( it, new QskHintAnimator( aspect, index ) );
|
||||
}
|
||||
|
||||
return *it;
|
||||
}
|
||||
|
||||
private:
|
||||
static inline bool lessThan( const QskHintAnimator* animator, const QskAspect& aspect )
|
||||
struct Key
|
||||
{
|
||||
return animator->aspect() < aspect;
|
||||
QskAspect aspect;
|
||||
int index;
|
||||
};
|
||||
|
||||
static inline bool lessThan( const QskHintAnimator* animator, const Key& key )
|
||||
{
|
||||
if ( animator->aspect() == key.aspect )
|
||||
return animator->index() < key.index;
|
||||
|
||||
return animator->aspect() < key.aspect;
|
||||
}
|
||||
};
|
||||
|
||||
@ -281,7 +308,7 @@ QskHintAnimatorTable::~QskHintAnimatorTable()
|
||||
}
|
||||
|
||||
void QskHintAnimatorTable::start( QskControl* control,
|
||||
QskAspect aspect, QskAnimationHint animationHint,
|
||||
const QskAspect aspect, int index, QskAnimationHint animationHint,
|
||||
const QVariant& from, const QVariant& to )
|
||||
{
|
||||
if ( m_data == nullptr )
|
||||
@ -292,7 +319,7 @@ void QskHintAnimatorTable::start( QskControl* control,
|
||||
qskAnimatorGuard->registerTable( this );
|
||||
}
|
||||
|
||||
auto animator = m_data->animators.findOrInsert( aspect );
|
||||
auto animator = m_data->animators.findOrInsert( aspect, index );
|
||||
|
||||
animator->setStartValue( from );
|
||||
animator->setEndValue( to );
|
||||
@ -308,24 +335,24 @@ void QskHintAnimatorTable::start( QskControl* control,
|
||||
|
||||
if ( qskCheckReceiverThread( control ) )
|
||||
{
|
||||
QskAnimatorEvent event( aspect, QskAnimatorEvent::Started );
|
||||
QskAnimatorEvent event( aspect, index, QskAnimatorEvent::Started );
|
||||
QCoreApplication::sendEvent( control, &event );
|
||||
}
|
||||
}
|
||||
|
||||
const QskHintAnimator* QskHintAnimatorTable::animator( QskAspect aspect ) const
|
||||
const QskHintAnimator* QskHintAnimatorTable::animator( QskAspect aspect, int index ) const
|
||||
{
|
||||
if ( m_data )
|
||||
return m_data->animators.find( aspect );
|
||||
return m_data->animators.find( aspect, index );
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QVariant QskHintAnimatorTable::currentValue( QskAspect aspect ) const
|
||||
QVariant QskHintAnimatorTable::currentValue( QskAspect aspect, int index ) const
|
||||
{
|
||||
if ( m_data )
|
||||
{
|
||||
if ( auto animator = m_data->animators.find( aspect ) )
|
||||
if ( auto animator = m_data->animators.find( aspect, index ) )
|
||||
{
|
||||
if ( animator->isRunning() )
|
||||
return animator->currentValue();
|
||||
@ -340,7 +367,7 @@ bool QskHintAnimatorTable::cleanup()
|
||||
if ( m_data == nullptr )
|
||||
return true;
|
||||
|
||||
auto &animators = m_data->animators;
|
||||
auto& animators = m_data->animators;
|
||||
|
||||
for ( auto it = animators.begin(); it != animators.end(); )
|
||||
{
|
||||
@ -351,6 +378,7 @@ bool QskHintAnimatorTable::cleanup()
|
||||
{
|
||||
const auto control = animator->control();
|
||||
const auto aspect = animator->aspect();
|
||||
const auto index = animator->index();
|
||||
|
||||
delete animator;
|
||||
|
||||
@ -360,7 +388,9 @@ bool QskHintAnimatorTable::cleanup()
|
||||
{
|
||||
if ( qskCheckReceiverThread( control ) )
|
||||
{
|
||||
auto event = new QskAnimatorEvent( aspect, QskAnimatorEvent::Terminated );
|
||||
auto event = new QskAnimatorEvent(
|
||||
aspect, index, QskAnimatorEvent::Terminated );
|
||||
|
||||
QCoreApplication::postEvent( control, event );
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,17 @@ class QSK_EXPORT QskHintAnimator : public QskVariantAnimator
|
||||
using Inherited = QskVariantAnimator;
|
||||
|
||||
public:
|
||||
QskHintAnimator( QskAspect = QskAspect() ) noexcept;
|
||||
QskHintAnimator() noexcept = default;
|
||||
QskHintAnimator( QskAspect, int index ) noexcept;
|
||||
|
||||
~QskHintAnimator() override;
|
||||
|
||||
void setAspect( QskAspect ) noexcept;
|
||||
QskAspect aspect() const noexcept;
|
||||
|
||||
void setIndex( int ) noexcept;
|
||||
int index() const noexcept;
|
||||
|
||||
void setControl( QskControl* ) noexcept;
|
||||
QskControl* control() const noexcept;
|
||||
|
||||
@ -37,6 +42,7 @@ class QSK_EXPORT QskHintAnimator : public QskVariantAnimator
|
||||
|
||||
private:
|
||||
QskAspect m_aspect;
|
||||
int m_index = -1;
|
||||
QskAnimationHint::UpdateFlags m_updateFlags;
|
||||
QPointer< QskControl > m_control;
|
||||
};
|
||||
@ -54,11 +60,11 @@ class QSK_EXPORT QskHintAnimatorTable
|
||||
QskHintAnimatorTable();
|
||||
~QskHintAnimatorTable();
|
||||
|
||||
void start( QskControl*, QskAspect,
|
||||
void start( QskControl*, QskAspect, int index,
|
||||
QskAnimationHint, const QVariant& from, const QVariant& to );
|
||||
|
||||
const QskHintAnimator* animator( QskAspect ) const;
|
||||
QVariant currentValue( QskAspect ) const;
|
||||
const QskHintAnimator* animator( QskAspect, int index = -1 ) const;
|
||||
QVariant currentValue( QskAspect, int index = -1 ) const;
|
||||
|
||||
bool cleanup();
|
||||
bool isEmpty() const;
|
||||
@ -75,6 +81,11 @@ inline QskAspect QskHintAnimator::aspect() const noexcept
|
||||
return m_aspect;
|
||||
}
|
||||
|
||||
inline int QskHintAnimator::index() const noexcept
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
inline QskAnimationHint::UpdateFlags QskHintAnimator::updateFlags() const noexcept
|
||||
{
|
||||
return m_updateFlags;
|
||||
|
@ -371,6 +371,7 @@ void QskSegmentedBar::setSelectedIndex( int index )
|
||||
|
||||
if( index != m_data->selectedIndex )
|
||||
{
|
||||
const auto oldIndex = m_data->selectedIndex;
|
||||
m_data->selectedIndex = index;
|
||||
|
||||
movePositionHint( Cursor, index );
|
||||
@ -380,6 +381,14 @@ void QskSegmentedBar::setSelectedIndex( int index )
|
||||
|
||||
setSkinStateFlag( Minimum, ( m_data->selectedIndex == 0 ) );
|
||||
setSkinStateFlag( Maximum, ( m_data->selectedIndex == count() - 1 ) );
|
||||
|
||||
const auto states = skinStates();
|
||||
|
||||
if ( oldIndex >= 0 )
|
||||
startHintTransitions( states | Selected, states, oldIndex );
|
||||
|
||||
if ( index >= 0 )
|
||||
startHintTransitions( states, states | Selected, index );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,6 +242,8 @@ class QskSkinlet::PrivateData
|
||||
QskSkin* skin;
|
||||
QVector< quint8 > nodeRoles;
|
||||
|
||||
int animatorIndex = -1;
|
||||
|
||||
bool ownedBySkinnable : 1;
|
||||
};
|
||||
|
||||
@ -269,6 +271,21 @@ bool QskSkinlet::isOwnedBySkinnable() const
|
||||
return m_data->ownedBySkinnable;
|
||||
}
|
||||
|
||||
void QskSkinlet::setAnimatorIndex( int index )
|
||||
{
|
||||
m_data->animatorIndex = index;
|
||||
}
|
||||
|
||||
void QskSkinlet::resetAnimatorIndex()
|
||||
{
|
||||
m_data->animatorIndex = -1;
|
||||
}
|
||||
|
||||
int QskSkinlet::animatorIndex() const
|
||||
{
|
||||
return m_data->animatorIndex;
|
||||
}
|
||||
|
||||
void QskSkinlet::setNodeRoles( const QVector< quint8 >& nodeRoles )
|
||||
{
|
||||
m_data->nodeRoles = nodeRoles;
|
||||
@ -693,6 +710,25 @@ QSGNode* QskSkinlet::updateSeriesNode( const QskSkinnable* skinnable,
|
||||
QskSkinStateChanger stateChanger( skinnable );
|
||||
stateChanger.setStates( newStates );
|
||||
|
||||
class IndexChanger
|
||||
{
|
||||
public:
|
||||
inline IndexChanger( const QskSkinlet* skinlet, int index )
|
||||
: m_skinlet( const_cast< QskSkinlet* >( skinlet ) )
|
||||
{
|
||||
m_skinlet->setAnimatorIndex( index );
|
||||
}
|
||||
|
||||
inline ~IndexChanger()
|
||||
{
|
||||
m_skinlet->resetAnimatorIndex();
|
||||
}
|
||||
private:
|
||||
QskSkinlet* m_skinlet;
|
||||
};
|
||||
|
||||
IndexChanger indexChanger( this, i );
|
||||
|
||||
newNode = updateSampleNode( skinnable, subControl, i, node );
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,10 @@ class QSK_EXPORT QskSkinlet
|
||||
void setOwnedBySkinnable( bool on );
|
||||
bool isOwnedBySkinnable() const;
|
||||
|
||||
void setAnimatorIndex( int );
|
||||
void resetAnimatorIndex();
|
||||
int animatorIndex() const;
|
||||
|
||||
// Helper functions for creating nodes
|
||||
|
||||
static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,
|
||||
|
@ -938,13 +938,11 @@ QVariant QskSkinnable::animatedHint(
|
||||
|
||||
if ( !m_data->animators.isEmpty() )
|
||||
{
|
||||
/*
|
||||
The local animators were invented to be stateless
|
||||
and we never have an aspect with a state here.
|
||||
But that might change ...
|
||||
*/
|
||||
const int index = effectiveSkinlet()->animatorIndex();
|
||||
|
||||
v = m_data->animators.currentValue( aspect );
|
||||
v = m_data->animators.currentValue( aspect, index );
|
||||
if ( !v.isValid() && index >= 0 )
|
||||
v = m_data->animators.currentValue( aspect, -1 );
|
||||
}
|
||||
|
||||
if ( status && v.isValid() )
|
||||
@ -1221,11 +1219,17 @@ bool QskSkinnable::isTransitionAccepted( QskAspect aspect ) const
|
||||
void QskSkinnable::startTransition( QskAspect aspect,
|
||||
QskAnimationHint animationHint, const QVariant& from, const QVariant& to )
|
||||
{
|
||||
aspect.setSubControl( effectiveSubcontrol( aspect.subControl() ) );
|
||||
startHintTransition( aspect, animationHint, from, to );
|
||||
startTransition( aspect, -1, animationHint, from, to );
|
||||
}
|
||||
|
||||
void QskSkinnable::startHintTransition( QskAspect aspect,
|
||||
void QskSkinnable::startTransition( QskAspect aspect, int index,
|
||||
QskAnimationHint animationHint, const QVariant& from, const QVariant& to )
|
||||
{
|
||||
aspect.setSubControl( effectiveSubcontrol( aspect.subControl() ) );
|
||||
startHintTransition( aspect, index, animationHint, from, to );
|
||||
}
|
||||
|
||||
void QskSkinnable::startHintTransition( QskAspect aspect, int index,
|
||||
QskAnimationHint animationHint, const QVariant& from, const QVariant& to )
|
||||
{
|
||||
if ( animationHint.duration <= 0 || ( from == to ) )
|
||||
@ -1263,11 +1267,11 @@ void QskSkinnable::startHintTransition( QskAspect aspect,
|
||||
qDebug() << aspect << animationHint.duration;
|
||||
#endif
|
||||
|
||||
auto animator = m_data->animators.animator( aspect );
|
||||
auto animator = m_data->animators.animator( aspect, index );
|
||||
if ( animator && animator->isRunning() )
|
||||
v1 = animator->currentValue();
|
||||
|
||||
m_data->animators.start( control, aspect, animationHint, v1, v2 );
|
||||
m_data->animators.start( control, aspect, index, animationHint, v1, v2 );
|
||||
}
|
||||
|
||||
void QskSkinnable::setSkinStateFlag( QskAspect::State stateFlag, bool on )
|
||||
@ -1333,7 +1337,7 @@ void QskSkinnable::setSkinStates( QskAspect::States newStates )
|
||||
}
|
||||
|
||||
bool QskSkinnable::startHintTransitions(
|
||||
QskAspect::States oldStates, QskAspect::States newStates )
|
||||
QskAspect::States oldStates, QskAspect::States newStates, int index )
|
||||
{
|
||||
if ( !isTransitionAccepted( QskAspect() ) )
|
||||
{
|
||||
@ -1390,13 +1394,13 @@ bool QskSkinnable::startHintTransitions(
|
||||
that are finally resolved from the same hint in
|
||||
the skin table.
|
||||
*/
|
||||
|
||||
|
||||
doTransition = !skinTable.isResolutionMatching( a1, a2 );
|
||||
}
|
||||
|
||||
if ( doTransition )
|
||||
{
|
||||
startHintTransition( aspect, hint,
|
||||
startHintTransition( aspect, index, hint,
|
||||
storedHint( a1 ), storedHint( a2 ) );
|
||||
|
||||
started = true;
|
||||
|
@ -124,6 +124,9 @@ class QSK_EXPORT QskSkinnable
|
||||
void startTransition( QskAspect,
|
||||
QskAnimationHint, const QVariant& from, const QVariant& to );
|
||||
|
||||
void startTransition( QskAspect, int index,
|
||||
QskAnimationHint, const QVariant& from, const QVariant& to );
|
||||
|
||||
QskAspect::Subcontrol effectiveSubcontrol( QskAspect::Subcontrol ) const;
|
||||
|
||||
QskControl* controlCast();
|
||||
@ -247,6 +250,8 @@ class QSK_EXPORT QskSkinnable
|
||||
|
||||
const QskSkinHintTable& hintTable() const;
|
||||
|
||||
bool startHintTransitions( QskAspect::States, QskAspect::States, int index = -1 );
|
||||
|
||||
protected:
|
||||
virtual void updateNode( QSGNode* );
|
||||
virtual bool isTransitionAccepted( QskAspect ) const;
|
||||
@ -258,8 +263,7 @@ class QSK_EXPORT QskSkinnable
|
||||
private:
|
||||
Q_DISABLE_COPY( QskSkinnable )
|
||||
|
||||
bool startHintTransitions( QskAspect::States, QskAspect::States );
|
||||
void startHintTransition( QskAspect,
|
||||
void startHintTransition( QskAspect, int index,
|
||||
QskAnimationHint, const QVariant& from, const QVariant& to );
|
||||
|
||||
QVariant animatedHint( QskAspect, QskSkinHintStatus* ) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user