tracking states of the aspects in a QskSkinHintTable
This commit is contained in:
parent
a38a4a101e
commit
1eae47aefa
|
@ -128,7 +128,6 @@ class QskSkin::PrivateData
|
||||||
std::unordered_map< const QMetaObject*, SkinletData > skinletMap;
|
std::unordered_map< const QMetaObject*, SkinletData > skinletMap;
|
||||||
|
|
||||||
QskSkinHintTable hintTable;
|
QskSkinHintTable hintTable;
|
||||||
QskAspect::States stateMask = QskAspect::AllStates;
|
|
||||||
|
|
||||||
std::unordered_map< int, QFont > fonts;
|
std::unordered_map< int, QFont > fonts;
|
||||||
std::unordered_map< int, QskColorFilter > graphicFilters;
|
std::unordered_map< int, QskColorFilter > graphicFilters;
|
||||||
|
@ -345,22 +344,6 @@ const int* QskSkin::dialogButtonLayout( Qt::Orientation orientation ) const
|
||||||
return QPlatformDialogHelper::buttonLayout( orientation, policy );
|
return QPlatformDialogHelper::buttonLayout( orientation, policy );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSkin::setStateMask( QskAspect::States mask )
|
|
||||||
{
|
|
||||||
for ( auto state : { QskControl::Disabled, QskControl::Hovered, QskControl::Focused } )
|
|
||||||
{
|
|
||||||
if ( mask & state )
|
|
||||||
m_data->stateMask |= state;
|
|
||||||
else
|
|
||||||
m_data->stateMask &= ~state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QskAspect::States QskSkin::stateMask() const
|
|
||||||
{
|
|
||||||
return m_data->stateMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
QskSkinlet* QskSkin::skinlet( const QMetaObject* metaObject )
|
QskSkinlet* QskSkin::skinlet( const QMetaObject* metaObject )
|
||||||
{
|
{
|
||||||
while ( metaObject )
|
while ( metaObject )
|
||||||
|
|
|
@ -77,9 +77,6 @@ class QSK_EXPORT QskSkin : public QObject
|
||||||
virtual const int* dialogButtonLayout( Qt::Orientation ) const;
|
virtual const int* dialogButtonLayout( Qt::Orientation ) const;
|
||||||
virtual QString dialogButtonText( int button ) const;
|
virtual QString dialogButtonText( int button ) const;
|
||||||
|
|
||||||
void setStateMask( QskAspect::States );
|
|
||||||
QskAspect::States stateMask() const;
|
|
||||||
|
|
||||||
QskSkinlet* skinlet( const QMetaObject* );
|
QskSkinlet* skinlet( const QMetaObject* );
|
||||||
|
|
||||||
const QskSkinHintTable& hintTable() const;
|
const QskSkinHintTable& hintTable() const;
|
||||||
|
|
|
@ -67,7 +67,7 @@ QskSkinHintTable::QskSkinHintTable()
|
||||||
QskSkinHintTable::QskSkinHintTable( const QskSkinHintTable& other )
|
QskSkinHintTable::QskSkinHintTable( const QskSkinHintTable& other )
|
||||||
: m_hints( nullptr )
|
: m_hints( nullptr )
|
||||||
, m_animatorCount( other.m_animatorCount )
|
, m_animatorCount( other.m_animatorCount )
|
||||||
, m_statefulCount( other.m_statefulCount )
|
, m_states( other.m_states )
|
||||||
{
|
{
|
||||||
if ( other.m_hints )
|
if ( other.m_hints )
|
||||||
m_hints = new HintMap( *( other.m_hints ) );
|
m_hints = new HintMap( *( other.m_hints ) );
|
||||||
|
@ -81,7 +81,7 @@ QskSkinHintTable::~QskSkinHintTable()
|
||||||
QskSkinHintTable& QskSkinHintTable::operator=( const QskSkinHintTable& other )
|
QskSkinHintTable& QskSkinHintTable::operator=( const QskSkinHintTable& other )
|
||||||
{
|
{
|
||||||
m_animatorCount = other.m_animatorCount;
|
m_animatorCount = other.m_animatorCount;
|
||||||
m_statefulCount = other.m_statefulCount;
|
m_states = other.m_states;
|
||||||
|
|
||||||
if ( other.m_hints )
|
if ( other.m_hints )
|
||||||
{
|
{
|
||||||
|
@ -126,11 +126,7 @@ bool QskSkinHintTable::setHint( QskAspect aspect, const QVariant& skinHint )
|
||||||
QSK_ASSERT_COUNTER( m_animatorCount );
|
QSK_ASSERT_COUNTER( m_animatorCount );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( aspect.hasStates() )
|
m_states |= aspect.states();
|
||||||
{
|
|
||||||
m_statefulCount++;
|
|
||||||
QSK_ASSERT_COUNTER( m_statefulCount );
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -158,8 +154,7 @@ bool QskSkinHintTable::removeHint( QskAspect aspect )
|
||||||
if ( aspect.isAnimator() )
|
if ( aspect.isAnimator() )
|
||||||
m_animatorCount--;
|
m_animatorCount--;
|
||||||
|
|
||||||
if ( aspect.hasStates() )
|
// how to clear m_states ? TODO ...
|
||||||
m_statefulCount--;
|
|
||||||
|
|
||||||
if ( m_hints->empty() )
|
if ( m_hints->empty() )
|
||||||
{
|
{
|
||||||
|
@ -184,8 +179,7 @@ QVariant QskSkinHintTable::takeHint( QskAspect aspect )
|
||||||
if ( aspect.isAnimator() )
|
if ( aspect.isAnimator() )
|
||||||
m_animatorCount--;
|
m_animatorCount--;
|
||||||
|
|
||||||
if ( aspect.hasStates() )
|
// how to clear m_states ? TODO ...
|
||||||
m_statefulCount--;
|
|
||||||
|
|
||||||
if ( m_hints->empty() )
|
if ( m_hints->empty() )
|
||||||
{
|
{
|
||||||
|
@ -206,14 +200,14 @@ void QskSkinHintTable::clear()
|
||||||
m_hints = nullptr;
|
m_hints = nullptr;
|
||||||
|
|
||||||
m_animatorCount = 0;
|
m_animatorCount = 0;
|
||||||
m_statefulCount = 0;
|
m_states = QskAspect::NoState;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVariant* QskSkinHintTable::resolvedHint(
|
const QVariant* QskSkinHintTable::resolvedHint(
|
||||||
QskAspect aspect, QskAspect* resolvedAspect ) const
|
QskAspect aspect, QskAspect* resolvedAspect ) const
|
||||||
{
|
{
|
||||||
if ( m_hints != nullptr )
|
if ( m_hints != nullptr )
|
||||||
return qskResolvedHint( aspect, *m_hints, resolvedAspect );
|
return qskResolvedHint( aspect & m_states, *m_hints, resolvedAspect );
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -223,7 +217,7 @@ QskAspect QskSkinHintTable::resolvedAspect( QskAspect aspect ) const
|
||||||
QskAspect a;
|
QskAspect a;
|
||||||
|
|
||||||
if ( m_hints != nullptr )
|
if ( m_hints != nullptr )
|
||||||
qskResolvedHint( aspect, *m_hints, &a );
|
qskResolvedHint( aspect & m_states, *m_hints, &a );
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
@ -233,6 +227,8 @@ QskAspect QskSkinHintTable::resolvedAnimator(
|
||||||
{
|
{
|
||||||
if ( m_hints && m_animatorCount > 0 )
|
if ( m_hints && m_animatorCount > 0 )
|
||||||
{
|
{
|
||||||
|
aspect &= m_states;
|
||||||
|
|
||||||
Q_FOREVER
|
Q_FOREVER
|
||||||
{
|
{
|
||||||
auto it = m_hints->find( aspect );
|
auto it = m_hints->find( aspect );
|
||||||
|
@ -268,15 +264,16 @@ bool QskSkinHintTable::setAnimation(
|
||||||
bool QskSkinHintTable::isResolutionMatching(
|
bool QskSkinHintTable::isResolutionMatching(
|
||||||
QskAspect aspect1, QskAspect aspect2 ) const
|
QskAspect aspect1, QskAspect aspect2 ) const
|
||||||
{
|
{
|
||||||
|
// remove states we do not have early
|
||||||
|
aspect1 &= m_states;
|
||||||
|
aspect2 &= m_states;
|
||||||
|
|
||||||
if ( aspect1 == aspect2 )
|
if ( aspect1 == aspect2 )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if ( aspect1.trunk() != aspect2.trunk() )
|
if ( aspect1.trunk() != aspect2.trunk() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( !hasStates() )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const auto a1 = aspect1;
|
const auto a1 = aspect1;
|
||||||
const auto a2 = aspect2;
|
const auto a2 = aspect2;
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,10 @@ class QSK_EXPORT QskSkinHintTable
|
||||||
const std::unordered_map< QskAspect, QVariant >& hints() const;
|
const std::unordered_map< QskAspect, QVariant >& hints() const;
|
||||||
|
|
||||||
bool hasAnimators() const;
|
bool hasAnimators() const;
|
||||||
bool hasStates() const;
|
|
||||||
bool hasHints() const;
|
bool hasHints() const;
|
||||||
|
|
||||||
|
QskAspect::States states() const;
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
const QVariant* resolvedHint( QskAspect,
|
const QVariant* resolvedHint( QskAspect,
|
||||||
|
@ -62,7 +63,7 @@ class QSK_EXPORT QskSkinHintTable
|
||||||
HintMap* m_hints = nullptr;
|
HintMap* m_hints = nullptr;
|
||||||
|
|
||||||
unsigned short m_animatorCount = 0;
|
unsigned short m_animatorCount = 0;
|
||||||
unsigned short m_statefulCount = 0;
|
QskAspect::States m_states;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool QskSkinHintTable::hasHints() const
|
inline bool QskSkinHintTable::hasHints() const
|
||||||
|
@ -70,9 +71,9 @@ inline bool QskSkinHintTable::hasHints() const
|
||||||
return m_hints != nullptr;
|
return m_hints != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool QskSkinHintTable::hasStates() const
|
inline QskAspect::States QskSkinHintTable::states() const
|
||||||
{
|
{
|
||||||
return m_statefulCount > 0;
|
return m_states;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool QskSkinHintTable::hasAnimators() const
|
inline bool QskSkinHintTable::hasAnimators() const
|
||||||
|
|
|
@ -940,23 +940,12 @@ const QVariant& QskSkinnable::storedHint(
|
||||||
{
|
{
|
||||||
const auto skin = effectiveSkin();
|
const auto skin = effectiveSkin();
|
||||||
|
|
||||||
// clearing all state bits not being handled from the skin
|
|
||||||
aspect.clearStates( ~skin->stateMask() );
|
|
||||||
|
|
||||||
QskAspect resolvedAspect;
|
QskAspect resolvedAspect;
|
||||||
|
|
||||||
const auto& localTable = m_data->hintTable;
|
const auto& localTable = m_data->hintTable;
|
||||||
if ( localTable.hasHints() )
|
if ( localTable.hasHints() )
|
||||||
{
|
{
|
||||||
auto a = aspect;
|
if ( const auto value = localTable.resolvedHint( aspect, &resolvedAspect ) )
|
||||||
|
|
||||||
if ( !localTable.hasStates() )
|
|
||||||
{
|
|
||||||
// we don't need to clear the state bits stepwise
|
|
||||||
a.clearStates();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( const QVariant* value = localTable.resolvedHint( a, &resolvedAspect ) )
|
|
||||||
{
|
{
|
||||||
if ( status )
|
if ( status )
|
||||||
{
|
{
|
||||||
|
@ -972,10 +961,7 @@ const QVariant& QskSkinnable::storedHint(
|
||||||
const auto& skinTable = skin->hintTable();
|
const auto& skinTable = skin->hintTable();
|
||||||
if ( skinTable.hasHints() )
|
if ( skinTable.hasHints() )
|
||||||
{
|
{
|
||||||
auto a = aspect;
|
if ( const auto value = skinTable.resolvedHint( aspect, &resolvedAspect ) )
|
||||||
|
|
||||||
const QVariant* value = skinTable.resolvedHint( a, &resolvedAspect );
|
|
||||||
if ( value )
|
|
||||||
{
|
{
|
||||||
if ( status )
|
if ( status )
|
||||||
{
|
{
|
||||||
|
@ -993,8 +979,7 @@ const QVariant& QskSkinnable::storedHint(
|
||||||
aspect.setSubControl( QskAspect::Control );
|
aspect.setSubControl( QskAspect::Control );
|
||||||
aspect.clearStates();
|
aspect.clearStates();
|
||||||
|
|
||||||
value = skinTable.resolvedHint( aspect, &resolvedAspect );
|
if ( const auto value = skinTable.resolvedHint( aspect, &resolvedAspect ) )
|
||||||
if ( value )
|
|
||||||
{
|
{
|
||||||
if ( status )
|
if ( status )
|
||||||
{
|
{
|
||||||
|
@ -1257,7 +1242,8 @@ void QskSkinnable::setSkinStates( QskAspect::States newStates )
|
||||||
|
|
||||||
if ( skin )
|
if ( skin )
|
||||||
{
|
{
|
||||||
const auto mask = skin->stateMask();
|
const auto mask = skin->hintTable().states() | m_data->hintTable.states();
|
||||||
|
|
||||||
if ( ( newStates & mask ) == ( m_data->skinStates & mask ) )
|
if ( ( newStates & mask ) == ( m_data->skinStates & mask ) )
|
||||||
{
|
{
|
||||||
// the modified bits are not handled by the skin
|
// the modified bits are not handled by the skin
|
||||||
|
@ -1297,24 +1283,13 @@ void QskSkinnable::setSkinStates( QskAspect::States newStates )
|
||||||
const auto primitive = static_cast< QskAspect::Primitive >( i );
|
const auto primitive = static_cast< QskAspect::Primitive >( i );
|
||||||
aspect.setPrimitive( type, primitive );
|
aspect.setPrimitive( type, primitive );
|
||||||
|
|
||||||
auto a1 = aspect | m_data->skinStates;
|
const auto a1 = aspect | m_data->skinStates;
|
||||||
auto a2 = aspect | newStates;
|
const auto a2 = aspect | newStates;
|
||||||
|
|
||||||
bool doTransition = true;
|
bool doTransition = true;
|
||||||
|
|
||||||
if ( !m_data->hintTable.hasStates() )
|
if ( m_data->hintTable.states() == QskAspect::NoState )
|
||||||
{
|
|
||||||
/*
|
|
||||||
The hints are found by stripping the state bits one by
|
|
||||||
one until a lookup into the hint table is successful.
|
|
||||||
So for deciding whether two aspects lead to the same hint
|
|
||||||
we can stop as soon as the aspects have the same state bits.
|
|
||||||
This way we can reduce the number of lookups significantly
|
|
||||||
for skinnables with many state bits.
|
|
||||||
|
|
||||||
*/
|
|
||||||
doTransition = !skinTable.isResolutionMatching( a1, a2 );
|
doTransition = !skinTable.isResolutionMatching( a1, a2 );
|
||||||
}
|
|
||||||
|
|
||||||
if ( doTransition )
|
if ( doTransition )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue