QskSkinHintTable introduced to share more code between accessing local

and global hints
This commit is contained in:
Uwe Rathmann 2017-08-22 20:50:55 +02:00
parent a57915c6f0
commit 13d6719a5f
8 changed files with 348 additions and 198 deletions

View File

@ -12,6 +12,7 @@
#include "QskSetup.h" #include "QskSetup.h"
#include "QskAnimationHint.h" #include "QskAnimationHint.h"
#include "QskStandardSymbol.h" #include "QskStandardSymbol.h"
#include "QskSkinHintTable.h"
#include "QskFocusIndicator.h" #include "QskFocusIndicator.h"
@ -105,15 +106,15 @@ class QskSkin::PrivateData
{ {
public: public:
PrivateData( QskSkin* skin ): PrivateData( QskSkin* skin ):
skin( skin ) skin( skin ),
hintTable( true )
{ {
} }
QskSkin* skin; QskSkin* skin;
std::unordered_map< const QMetaObject*, SkinletData > skinletMap; std::unordered_map< const QMetaObject*, SkinletData > skinletMap;
std::unordered_map< QskAspect::Aspect, QVariant > skinHints; QskSkinHintTable hintTable;
std::unordered_map< int, std::set< QskAspect::Aspect > > animatorAspects;
std::unordered_map< int, QFont > fonts; std::unordered_map< int, QFont > fonts;
std::unordered_map< int, QskColorFilter > graphicFilters; std::unordered_map< int, QskColorFilter > graphicFilters;
@ -170,98 +171,38 @@ void QskSkin::setColor( QskAspect::Aspect aspect, const QColor& color )
QColor QskSkin::color( QskAspect::Aspect aspect ) const QColor QskSkin::color( QskAspect::Aspect aspect ) const
{ {
return skinHint( aspect | QskAspect::Color ).value<QColor>(); return m_data->hintTable.color( aspect );
} }
void QskSkin::setMetric( QskAspect::Aspect aspect, qreal metric ) void QskSkin::setMetric( QskAspect::Aspect aspect, qreal metric )
{ {
setSkinHint( aspect | QskAspect::Metric, metric ); m_data->hintTable.setMetric( aspect, metric );
} }
qreal QskSkin::metric( QskAspect::Aspect aspect ) const qreal QskSkin::metric( QskAspect::Aspect aspect ) const
{ {
return skinHint( aspect | QskAspect::Metric ).toReal(); return m_data->hintTable.metric( aspect );
} }
void QskSkin::setAnimation( void QskSkin::setAnimation(
QskAspect::Aspect aspect, QskAnimationHint animation ) QskAspect::Aspect aspect, QskAnimationHint animation )
{ {
aspect.setAnimator( true ); m_data->hintTable.setAnimation( aspect, animation );
setSkinHint( aspect, QVariant::fromValue( animation ) );
} }
QskAnimationHint QskSkin::animation( QskAspect::Aspect aspect ) const QskAnimationHint QskSkin::animation( QskAspect::Aspect aspect ) const
{ {
aspect.setAnimator( true ); return m_data->hintTable.animation( aspect );
return skinHint( aspect ).value< QskAnimationHint >();
} }
void QskSkin::setSkinHint( QskAspect::Aspect aspect, const QVariant& skinHint ) void QskSkin::setSkinHint( QskAspect::Aspect aspect, const QVariant& skinHint )
{ {
// For edges/corners, add all the implied assignments m_data->hintTable.setSkinHint( aspect, skinHint );
if ( aspect.isBoxPrimitive() )
{
if ( aspect.boxPrimitive() == QskAspect::Radius )
{
setSkinHint( aspect | QskAspect::RadiusX, skinHint );
setSkinHint( aspect | QskAspect::RadiusY, skinHint );
return;
}
const auto edges = aspect.edge();
const auto bitcount = qPopulationCount( static_cast<quint8>( edges ) );
if ( !bitcount || bitcount > 1 )
{
using namespace QskAspect;
auto aspectEdges = aspect;
aspectEdges.clearEdge();
if ( !bitcount || edges & TopEdge )
setSkinHint( aspectEdges | TopEdge, skinHint );
if ( !bitcount || ( edges & LeftEdge ) )
setSkinHint( aspectEdges | LeftEdge, skinHint );
if ( !bitcount || ( edges & RightEdge ) )
setSkinHint( aspectEdges | RightEdge, skinHint );
if ( !bitcount || ( edges & BottomEdge ) )
setSkinHint( aspectEdges | BottomEdge, skinHint );
}
if ( bitcount > 1 ) // Allows 0 to imply AllEdges
return;
}
auto it = m_data->skinHints.find( aspect );
if ( it == m_data->skinHints.end() )
{
m_data->skinHints.emplace( aspect, skinHint );
}
else if ( it->second != skinHint )
{
it->second = skinHint;
}
if ( aspect.isAnimator() )
m_data->animatorAspects[ aspect.subControl() ].insert( aspect );
}
void QskSkin::removeSkinHint( QskAspect::Aspect aspect )
{
m_data->skinHints.erase( aspect );
} }
const QVariant& QskSkin::skinHint( QskAspect::Aspect aspect ) const const QVariant& QskSkin::skinHint( QskAspect::Aspect aspect ) const
{ {
auto it = m_data->skinHints.find( aspect ); return m_data->hintTable.skinHint( aspect );
if ( it != m_data->skinHints.cend() )
return it->second;
static QVariant invalidHint;
return invalidHint;
} }
void QskSkin::declareSkinlet( const QMetaObject* metaObject, void QskSkin::declareSkinlet( const QMetaObject* metaObject,
@ -351,9 +292,14 @@ QskColorFilter QskSkin::graphicFilter( int graphicRole ) const
return QskColorFilter(); return QskColorFilter();
} }
const std::unordered_map< QskAspect::Aspect, QVariant >& QskSkin::skinHints() const const QskSkinHintTable& QskSkin::hintTable() const
{ {
return m_data->skinHints; return m_data->hintTable;
}
QskSkinHintTable& QskSkin::skinHintTable()
{
return m_data->hintTable;
} }
const std::unordered_map< int, QFont >& QskSkin::fonts() const const std::unordered_map< int, QFont >& QskSkin::fonts() const
@ -366,17 +312,6 @@ const std::unordered_map< int, QskColorFilter >& QskSkin::graphicFilters() const
return m_data->graphicFilters; return m_data->graphicFilters;
} }
const std::set< QskAspect::Aspect >& QskSkin::animatorAspects(
QskAspect::Subcontrol subControl ) const
{
auto it = m_data->animatorAspects.find( subControl );
if ( it != m_data->animatorAspects.cend() )
return it->second;
static std::set< QskAspect::Aspect > dummyAspects;
return dummyAspects;
}
QskGraphic QskSkin::symbol( int symbolType ) const QskGraphic QskSkin::symbol( int symbolType ) const
{ {
// should this one be somehow related to the platform icons ??? // should this one be somehow related to the platform icons ???

View File

@ -13,7 +13,6 @@
#include <QColor> #include <QColor>
#include <unordered_map> #include <unordered_map>
#include <set>
#include <memory> #include <memory>
#include <type_traits> #include <type_traits>
@ -26,6 +25,7 @@ class QskGraphic;
class QskGraphicProvider; class QskGraphicProvider;
class QskAnimationHint; class QskAnimationHint;
class QskSkinHintTable;
class QVariant; class QVariant;
@ -69,8 +69,6 @@ public:
QskAnimationHint animation( QskAspect::Aspect ) const; QskAnimationHint animation( QskAspect::Aspect ) const;
void setSkinHint( QskAspect::Aspect, const QVariant& hint ); void setSkinHint( QskAspect::Aspect, const QVariant& hint );
void removeSkinHint( QskAspect::Aspect );
const QVariant& skinHint( QskAspect::Aspect ) const; const QVariant& skinHint( QskAspect::Aspect ) const;
void setGraphicFilter( int graphicRole, const QskColorFilter& ); void setGraphicFilter( int graphicRole, const QskColorFilter& );
@ -94,11 +92,14 @@ public:
QskSkinlet* skinlet( const QskSkinnable* ); QskSkinlet* skinlet( const QskSkinnable* );
const std::set< QskAspect::Aspect >& animatorAspects( QskAspect::Subcontrol ) const; const QskSkinHintTable& hintTable() const;
const std::unordered_map< QskAspect::Aspect, QVariant >& skinHints() const;
const std::unordered_map< int, QFont >& fonts() const; const std::unordered_map< int, QFont >& fonts() const;
const std::unordered_map< int, QskColorFilter >& graphicFilters() const; const std::unordered_map< int, QskColorFilter >& graphicFilters() const;
protected:
QskSkinHintTable& skinHintTable();
private: private:
void declareSkinlet( const QMetaObject* controlMetaObject, void declareSkinlet( const QMetaObject* controlMetaObject,
const QMetaObject* skinMetaObject ); const QMetaObject* skinMetaObject );

View File

@ -0,0 +1,137 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskSkinHintTable.h"
QskSkinHintTable::QskSkinHintTable( bool extraAnimatorLookup ):
m_hints( nullptr ),
m_animatorAspects( nullptr )
{
if ( extraAnimatorLookup )
m_animatorAspects = new std::unordered_map< int, std::set< QskAspect::Aspect > >();
}
QskSkinHintTable::~QskSkinHintTable()
{
delete m_hints;
delete m_animatorAspects;
}
const std::set< QskAspect::Aspect >& QskSkinHintTable::animatorAspects(
QskAspect::Subcontrol subControl ) const
{
if ( m_animatorAspects )
{
auto it = m_animatorAspects->find( subControl );
if ( it != m_animatorAspects->cend() )
return it->second;
}
static std::set< QskAspect::Aspect > dummyAspects;
return dummyAspects;
}
const std::unordered_map< QskAspect::Aspect, QVariant >& QskSkinHintTable::hints() const
{
if ( m_hints )
return *m_hints;
static std::unordered_map< QskAspect::Aspect, QVariant > dummyHints;
return dummyHints;
}
void QskSkinHintTable::setSkinHint( QskAspect::Aspect aspect, const QVariant& skinHint )
{
// For edges/corners, add all the implied assignments
if ( aspect.isBoxPrimitive() )
{
if ( aspect.boxPrimitive() == QskAspect::Radius )
{
setSkinHint( aspect | QskAspect::RadiusX, skinHint );
setSkinHint( aspect | QskAspect::RadiusY, skinHint );
return;
}
const auto edges = aspect.edge();
const auto bitcount = qPopulationCount( static_cast< quint8 >( edges ) );
if ( !bitcount || bitcount > 1 )
{
using namespace QskAspect;
auto aspectEdges = aspect;
aspectEdges.clearEdge();
if ( !bitcount || edges & TopEdge )
setSkinHint( aspectEdges | TopEdge, skinHint );
if ( !bitcount || ( edges & LeftEdge ) )
setSkinHint( aspectEdges | LeftEdge, skinHint );
if ( !bitcount || ( edges & RightEdge ) )
setSkinHint( aspectEdges | RightEdge, skinHint );
if ( !bitcount || ( edges & BottomEdge ) )
setSkinHint( aspectEdges | BottomEdge, skinHint );
}
if ( bitcount > 1 ) // Allows 0 to imply AllEdges
return;
}
if ( m_hints == nullptr )
m_hints = new std::remove_pointer< decltype( m_hints ) >::type;
auto it = m_hints->find( aspect );
if ( it == m_hints->end() )
{
m_hints->emplace( aspect, skinHint );
}
else if ( it->second != skinHint )
{
it->second = skinHint;
}
if ( m_animatorAspects && aspect.isAnimator() )
( *m_animatorAspects )[ aspect.subControl() ].insert( aspect );
}
void QskSkinHintTable::removeSkinHint( QskAspect::Aspect aspect )
{
if ( m_hints == nullptr )
return;
m_hints->erase( aspect );
if ( m_hints->empty() )
{
delete m_hints;
m_hints = nullptr;
}
if ( m_animatorAspects && aspect.isAnimator() )
{
auto it = m_animatorAspects->find( aspect.subControl() );
if ( it != m_animatorAspects->end() )
{
auto& aspects = it->second;
aspects.erase( aspect );
if ( aspects.empty() )
m_animatorAspects->erase( it );
}
}
}
const QVariant& QskSkinHintTable::skinHint( QskAspect::Aspect aspect ) const
{
if ( m_hints )
{
auto it = m_hints->find( aspect );
if ( it != m_hints->cend() )
return it->second;
}
static QVariant invalidHint;
return invalidHint;
}

View File

@ -0,0 +1,131 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_SKIN_HINT_TABLE_H
#define QSK_SKIN_HINT_TABLE_H
#include "QskGlobal.h"
#include "QskAspect.h"
#include "QskAnimationHint.h"
#include <QVariant>
#include <QColor>
#include <unordered_map>
#include <set>
class QSK_EXPORT QskSkinHintTable
{
public:
QskSkinHintTable( bool extraAnimatorLookup );
~QskSkinHintTable();
void setColor( QskAspect::Aspect, Qt::GlobalColor );
void setColor( QskAspect::Aspect, QRgb );
void setColor( QskAspect::Aspect, const QColor& );
QColor color( QskAspect::Aspect aspect ) const;
void setMetric( QskAspect::Aspect, qreal metric );
qreal metric( QskAspect::Aspect ) const;
void setAnimation( QskAspect::Aspect, QskAnimationHint animation );
QskAnimationHint animation( QskAspect::Aspect ) const;
void setGraphicRole( QskAspect::Aspect, int role );
void setFontRole( QskAspect::Aspect, int role );
void setFlagHint( QskAspect::Aspect, int flag );
bool hasAnimatorLookup() const;
void setSkinHint( QskAspect::Aspect, const QVariant& );
const QVariant& skinHint( QskAspect::Aspect ) const;
void removeSkinHint( QskAspect::Aspect );
bool hasHint( QskAspect::Aspect ) const;
const std::set< QskAspect::Aspect >& animatorAspects( QskAspect::Subcontrol ) const;
const std::unordered_map< QskAspect::Aspect, QVariant >& hints() const;
private:
std::unordered_map< QskAspect::Aspect, QVariant >* m_hints;
std::unordered_map< int, std::set< QskAspect::Aspect > >* m_animatorAspects;
};
inline bool QskSkinHintTable::hasAnimatorLookup() const
{
return m_animatorAspects != nullptr;
}
inline bool QskSkinHintTable::hasHint( QskAspect::Aspect aspect ) const
{
if ( m_hints )
return m_hints->find( aspect ) != m_hints->cend();
return false;
}
inline void QskSkinHintTable::setColor(
QskAspect::Aspect aspect, const QColor& color )
{
setSkinHint( aspect | QskAspect::Color, color );
}
inline void QskSkinHintTable::setColor(
QskAspect::Aspect aspect, Qt::GlobalColor color )
{
setSkinHint( aspect | QskAspect::Color, QColor( color ) );
}
inline void QskSkinHintTable::setColor(
QskAspect::Aspect aspect, QRgb rgb )
{
setSkinHint( aspect | QskAspect::Color, QColor::fromRgba( rgb ) );
}
inline QColor QskSkinHintTable::color( QskAspect::Aspect aspect ) const
{
return skinHint( aspect | QskAspect::Color ).value<QColor>();
}
inline void QskSkinHintTable::setMetric( QskAspect::Aspect aspect, qreal metric )
{
setSkinHint( aspect | QskAspect::Metric, metric );
}
inline qreal QskSkinHintTable::metric( QskAspect::Aspect aspect ) const
{
return skinHint( aspect | QskAspect::Metric ).toReal();
}
inline void QskSkinHintTable::setAnimation(
QskAspect::Aspect aspect, QskAnimationHint animation )
{
aspect.setAnimator( true );
setSkinHint( aspect, QVariant::fromValue( animation ) );
}
inline QskAnimationHint QskSkinHintTable::animation( QskAspect::Aspect aspect ) const
{
aspect.setAnimator( true );
return skinHint( aspect ).value< QskAnimationHint >();
}
inline void QskSkinHintTable::setGraphicRole( QskAspect::Aspect aspect, int role )
{
setSkinHint( aspect | QskAspect::GraphicRole, role );
}
inline void QskSkinHintTable::setFontRole( QskAspect::Aspect aspect, int role )
{
setSkinHint( aspect | QskAspect::FontRole, role );
}
inline void QskSkinHintTable::setFlagHint( QskAspect::Aspect aspect, int flag )
{
setSkinHint( aspect, QVariant( flag ) );
}
#endif

View File

@ -1,6 +1,7 @@
#include "QskSkinTransition.h" #include "QskSkinTransition.h"
#include "QskControl.h" #include "QskControl.h"
#include "QskSkin.h" #include "QskSkin.h"
#include "QskSkinHintTable.h"
#include "QskColorFilter.h" #include "QskColorFilter.h"
#include "QskHintAnimator.h" #include "QskHintAnimator.h"
@ -421,14 +422,14 @@ void QskSkinTransition::process()
// copy out all hints before updating the skin // copy out all hints before updating the skin
// - would be good to have Copy on Write here // - would be good to have Copy on Write here
const auto oldMap = m_skins[0]->skinHints(); const auto oldMap = m_skins[0]->hintTable().hints();
const auto oldFilters = m_skins[0]->graphicFilters(); const auto oldFilters = m_skins[0]->graphicFilters();
// apply the changes // apply the changes
updateSkin( m_skins[0], m_skins[1] ); updateSkin( m_skins[0], m_skins[1] );
candidates = qskAnimatorCandidates( m_mask, oldMap, oldFilters, candidates = qskAnimatorCandidates( m_mask, oldMap, oldFilters,
m_skins[1]->skinHints(), m_skins[1]->graphicFilters() ); m_skins[1]->hintTable().hints(), m_skins[1]->graphicFilters() );
} }
if ( !candidates.isEmpty() ) if ( !candidates.isEmpty() )

View File

@ -8,6 +8,7 @@
#include "QskAspect.h" #include "QskAspect.h"
#include "QskSetup.h" #include "QskSetup.h"
#include "QskSkin.h" #include "QskSkin.h"
#include "QskSkinHintTable.h"
#include "QskSkinlet.h" #include "QskSkinlet.h"
#include "QskAnimationHint.h" #include "QskAnimationHint.h"
#include "QskHintAnimator.h" #include "QskHintAnimator.h"
@ -121,7 +122,7 @@ class QskSkinnable::PrivateData
{ {
public: public:
PrivateData(): PrivateData():
skinHints( nullptr ), hintTable( false ),
skinlet( nullptr ), skinlet( nullptr ),
skinState( QskAspect::NoState ), skinState( QskAspect::NoState ),
hasLocalSkinlet( false ) hasLocalSkinlet( false )
@ -132,11 +133,9 @@ public:
{ {
if ( skinlet && skinlet->isOwnedBySkinnable() ) if ( skinlet && skinlet->isOwnedBySkinnable() )
delete skinlet; delete skinlet;
delete skinHints;
} }
std::unordered_map< QskAspect::Aspect, QVariant >* skinHints; QskSkinHintTable hintTable;
QskHintAnimatorTable animators; QskHintAnimatorTable animators;
@ -207,9 +206,19 @@ const QskSkinlet* QskSkinnable::effectiveSkinlet() const
return m_data->skinlet; return m_data->skinlet;
} }
QskSkinHintTable &QskSkinnable::hintTable()
{
return m_data->hintTable;
}
const QskSkinHintTable &QskSkinnable::hintTable() const
{
return m_data->hintTable;
}
void QskSkinnable::setFlagHint( QskAspect::Aspect aspect, int flag ) void QskSkinnable::setFlagHint( QskAspect::Aspect aspect, int flag )
{ {
setSkinHint( aspect, QVariant( flag ) ); m_data->hintTable.setSkinHint( aspect, QVariant( flag ) );
} }
int QskSkinnable::flagHint( QskAspect::Aspect aspect ) const int QskSkinnable::flagHint( QskAspect::Aspect aspect ) const
@ -219,12 +228,17 @@ int QskSkinnable::flagHint( QskAspect::Aspect aspect ) const
void QskSkinnable::setColor( QskAspect::Aspect aspect, const QColor& color ) void QskSkinnable::setColor( QskAspect::Aspect aspect, const QColor& color )
{ {
setSkinHint( aspect | QskAspect::Color, color ); m_data->hintTable.setColor( aspect, color );
} }
void QskSkinnable::setColor( QskAspect::Aspect aspect, Qt::GlobalColor color ) void QskSkinnable::setColor( QskAspect::Aspect aspect, Qt::GlobalColor color )
{ {
setSkinHint( aspect | QskAspect::Color, QColor( color ) ); m_data->hintTable.setColor( aspect, color );
}
void QskSkinnable::setColor( QskAspect::Aspect aspect, QRgb rgb )
{
m_data->hintTable.setColor( aspect, rgb );
} }
QColor QskSkinnable::color( QskAspect::Aspect aspect, QskSkinHintStatus* status ) const QColor QskSkinnable::color( QskAspect::Aspect aspect, QskSkinHintStatus* status ) const
@ -232,14 +246,9 @@ QColor QskSkinnable::color( QskAspect::Aspect aspect, QskSkinHintStatus* status
return effectiveHint( aspect | QskAspect::Color, status ).value< QColor >(); return effectiveHint( aspect | QskAspect::Color, status ).value< QColor >();
} }
void QskSkinnable::setColor( QskAspect::Aspect aspect, QRgb rgb )
{
setSkinHint( aspect | QskAspect::Color, QColor::fromRgba( rgb ) );
}
void QskSkinnable::setMetric( QskAspect::Aspect aspect, qreal metric ) void QskSkinnable::setMetric( QskAspect::Aspect aspect, qreal metric )
{ {
setSkinHint( aspect | QskAspect::Metric, metric ); m_data->hintTable.setMetric( aspect, metric );
} }
qreal QskSkinnable::metric( QskAspect::Aspect aspect, QskSkinHintStatus* status ) const qreal QskSkinnable::metric( QskAspect::Aspect aspect, QskSkinHintStatus* status ) const
@ -263,11 +272,7 @@ QMarginsF QskSkinnable::edgeMetrics( QskAspect::Subcontrol subControl,
void QskSkinnable::setFontRole( QskAspect::Aspect aspect, int role ) void QskSkinnable::setFontRole( QskAspect::Aspect aspect, int role )
{ {
setSkinHint( aspect | QskAspect::FontRole, role ); m_data->hintTable.setFontRole( aspect, role );
#if 1
if ( QskControl* control = owningControl() )
control->resetImplicitSize();
#endif
} }
int QskSkinnable::fontRole( QskAspect::Aspect aspect ) const int QskSkinnable::fontRole( QskAspect::Aspect aspect ) const
@ -282,7 +287,7 @@ QFont QskSkinnable::effectiveFont( QskAspect::Aspect aspect ) const
void QskSkinnable::setGraphicRole( QskAspect::Aspect aspect, int role ) void QskSkinnable::setGraphicRole( QskAspect::Aspect aspect, int role )
{ {
setSkinHint( aspect | QskAspect::GraphicRole, role ); m_data->hintTable.setGraphicRole( aspect, role );
} }
int QskSkinnable::graphicRole( QskAspect::Aspect aspect ) const int QskSkinnable::graphicRole( QskAspect::Aspect aspect ) const
@ -322,8 +327,7 @@ QskColorFilter QskSkinnable::effectiveGraphicFilter(
void QskSkinnable::setAnimation( void QskSkinnable::setAnimation(
QskAspect::Aspect aspect, QskAnimationHint animation ) QskAspect::Aspect aspect, QskAnimationHint animation )
{ {
aspect.setAnimator( true ); m_data->hintTable.setAnimation( aspect, animation );
setSkinHint( aspect, QVariant::fromValue( animation ) );
} }
QskAnimationHint QskSkinnable::animation( QskAnimationHint QskSkinnable::animation(
@ -333,60 +337,6 @@ QskAnimationHint QskSkinnable::animation(
return effectiveHint( aspect, status ).value< QskAnimationHint >(); return effectiveHint( aspect, status ).value< QskAnimationHint >();
} }
void QskSkinnable::setSkinHint( QskAspect::Aspect aspect, const QVariant& skinHint )
{
// For edges/corners, add all the implied assignments
if ( aspect.isBoxPrimitive() )
{
// Special case for Radius, which is actually two primitives
if ( aspect.boxPrimitive() == QskAspect::Radius )
{
setSkinHint( aspect | QskAspect::RadiusX, skinHint );
setSkinHint( aspect | QskAspect::RadiusY, skinHint );
return;
}
const auto edges = aspect.edge();
const auto bitcount = qPopulationCount( static_cast< quint8 >( edges ) );
if ( !bitcount || bitcount > 1 )
{
using namespace QskAspect;
auto aspectEdges = aspect;
aspectEdges.clearEdge();
if ( !bitcount || edges & TopEdge )
setSkinHint( aspectEdges | TopEdge, skinHint );
if ( !bitcount || ( edges & LeftEdge ) )
setSkinHint( aspectEdges | LeftEdge, skinHint );
if ( !bitcount || ( edges & RightEdge ) )
setSkinHint( aspectEdges | RightEdge, skinHint );
if ( !bitcount || ( edges & BottomEdge ) )
setSkinHint( aspectEdges | BottomEdge, skinHint );
}
if ( bitcount > 1 ) // Allows 0 to imply AllEdges
return;
}
if ( m_data->skinHints == nullptr )
m_data->skinHints = new std::remove_pointer< decltype( m_data->skinHints ) >::type;
auto it = m_data->skinHints->find( aspect );
if ( it == m_data->skinHints->end() )
{
m_data->skinHints->emplace( aspect, skinHint );
}
else if ( it->second != skinHint )
{
it->second = skinHint;
}
}
QVariant QskSkinnable::effectiveHint( QVariant QskSkinnable::effectiveHint(
QskAspect::Aspect aspect, QskSkinHintStatus* status ) const QskAspect::Aspect aspect, QskSkinHintStatus* status ) const
{ {
@ -463,18 +413,16 @@ QVariant QskSkinnable::animatedValue(
return v; return v;
} }
void QskSkinnable::removeSkinHint( QskAspect::Aspect aspect )
{
if ( m_data->skinHints )
m_data->skinHints->erase( aspect );
}
const QVariant& QskSkinnable::storedHint( const QVariant& QskSkinnable::storedHint(
QskAspect::Aspect aspect, QskSkinHintStatus* status ) const QskAspect::Aspect aspect, QskSkinHintStatus* status ) const
{ {
const auto skin = effectiveSkin(); const auto& localHints = m_data->hintTable.hints();
return qskResolvedHint( aspect, m_data->skinHints, const QskSkin* skin = effectiveSkin();
skin ? &skin->skinHints() : nullptr, status );
return qskResolvedHint( aspect,
!localHints.empty() ? &localHints : nullptr,
skin ? &skin->hintTable().hints() : nullptr,
status );
} }
QskAspect::State QskSkinnable::skinState() const QskAspect::State QskSkinnable::skinState() const
@ -746,11 +694,7 @@ void QskSkinnable::setSkinStateFlag( QskAspect::State state, bool on )
QskControl* control = owningControl(); QskControl* control = owningControl();
if ( control->window() && control->isInitiallyPainted() ) if ( control->window() && control->isInitiallyPainted() )
{ {
const auto localHints = m_data->skinHints; for ( const auto entry : m_data->hintTable.hints() )
if ( localHints )
{
for ( const auto entry : *localHints )
{ {
const auto aspect = entry.first; const auto aspect = entry.first;
if ( aspect.isAnimator() ) if ( aspect.isAnimator() )
@ -759,34 +703,33 @@ void QskSkinnable::setSkinStateFlag( QskAspect::State state, bool on )
startTransition( aspect, m_data->skinState, newState ); startTransition( aspect, m_data->skinState, newState );
} }
} }
}
const auto skin = effectiveSkin(); const QskSkin* skin = effectiveSkin();
auto subControls = control->subControls(); auto subControls = control->subControls();
#if 1 #if 1
subControls += QskAspect::Control; subControls += QskAspect::Control;
#endif #endif
const auto& hintTable = skin->hintTable();
for ( const auto subControl : subControls ) for ( const auto subControl : subControls )
{ {
const auto& animatorAspects = skin->animatorAspects( subControl ); const auto& animatorAspects = hintTable.animatorAspects( subControl );
for ( QskAspect::Aspect aspect : animatorAspects ) for ( QskAspect::Aspect aspect : animatorAspects )
{
if ( localHints && ( localHints->find( aspect ) != localHints->end() ) )
{ {
// ignore animators from the skin, when we have others // ignore animators from the skin, when we have others
// specifically defined for the skinnable // specifically defined for the skinnable
continue; if ( !m_data->hintTable.hasHint( aspect ) )
} {
if ( !aspect.state() || aspect.state() == newState ) if ( !aspect.state() || aspect.state() == newState )
startTransition( aspect, m_data->skinState, newState ); startTransition( aspect, m_data->skinState, newState );
} }
} }
} }
}
m_data->skinState = newState; m_data->skinState = newState;
control->update(); control->update();

View File

@ -30,6 +30,7 @@ class QskColorFilter;
class QskSkin; class QskSkin;
class QskSkinlet; class QskSkinlet;
class QskSkinHintTable;
class QSK_EXPORT QskSkinHintStatus class QSK_EXPORT QskSkinHintStatus
{ {
@ -95,8 +96,6 @@ public:
void setAnimation( QskAspect::Aspect, QskAnimationHint ); void setAnimation( QskAspect::Aspect, QskAnimationHint );
QskAnimationHint animation( QskAspect::Aspect, QskSkinHintStatus* = nullptr ) const; QskAnimationHint animation( QskAspect::Aspect, QskSkinHintStatus* = nullptr ) const;
void removeSkinHint( QskAspect::Aspect );
QVariant effectiveHint( QskAspect::Aspect, QskSkinHintStatus* = nullptr ) const; QVariant effectiveHint( QskAspect::Aspect, QskSkinHintStatus* = nullptr ) const;
QskSkinHintStatus hintStatus( QskAspect::Aspect ) const; QskSkinHintStatus hintStatus( QskAspect::Aspect ) const;
@ -134,9 +133,10 @@ protected:
void setSkinStateFlag( QskAspect::State, bool = true ); void setSkinStateFlag( QskAspect::State, bool = true );
virtual void updateNode( QSGNode* ); virtual void updateNode( QSGNode* );
private: QskSkinHintTable &hintTable();
void setSkinHint( QskAspect::Aspect, const QVariant& ); const QskSkinHintTable &hintTable() const;
private:
void startTransition( QskAspect::Aspect, QskAspect::State, QskAspect::State ); void startTransition( QskAspect::Aspect, QskAspect::State, QskAspect::State );
QVariant animatedValue( QskAspect::Aspect, QskSkinHintStatus* ) const; QVariant animatedValue( QskAspect::Aspect, QskSkinHintStatus* ) const;
const QVariant& storedHint( QskAspect::Aspect, QskSkinHintStatus* = nullptr ) const; const QVariant& storedHint( QskAspect::Aspect, QskSkinHintStatus* = nullptr ) const;

View File

@ -157,6 +157,7 @@ HEADERS += \
controls/QskSimpleListBox.h \ controls/QskSimpleListBox.h \
controls/QskSkinFactory.h \ controls/QskSkinFactory.h \
controls/QskSkin.h \ controls/QskSkin.h \
controls/QskSkinHintTable.h \
controls/QskAnimationHint.h \ controls/QskAnimationHint.h \
controls/QskSkinlet.h \ controls/QskSkinlet.h \
controls/QskSkinnable.h \ controls/QskSkinnable.h \
@ -220,6 +221,7 @@ SOURCES += \
controls/QskShortcut.cpp \ controls/QskShortcut.cpp \
controls/QskSimpleListBox.cpp \ controls/QskSimpleListBox.cpp \
controls/QskSkin.cpp \ controls/QskSkin.cpp \
controls/QskSkinHintTable.cpp \
controls/QskSkinFactory.cpp \ controls/QskSkinFactory.cpp \
controls/QskSkinlet.cpp \ controls/QskSkinlet.cpp \
controls/QskSkinnable.cpp \ controls/QskSkinnable.cpp \