qskinny/src/controls/QskSkinHintTable.cpp

216 lines
4.7 KiB
C++
Raw Normal View History

/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskSkinHintTable.h"
QVariant QskSkinHintTable::invalidHint;
inline const QVariant* qskResolvedHint( QskAspect::Aspect aspect,
const std::unordered_map< QskAspect::Aspect, QVariant >& hints,
QskAspect::Aspect* resolvedAspect )
{
const auto a = aspect;
Q_FOREVER
{
auto it = hints.find( aspect );
if ( it != hints.cend() )
{
if ( resolvedAspect )
*resolvedAspect = aspect;
return &it->second;
}
if ( const auto topState = aspect.topState() )
{
aspect.clearState( topState );
continue;
}
if ( aspect.placement() )
{
// clear the placement bits and restart
aspect = a;
aspect.setPlacement( QskAspect::NoPlacement );
continue;
}
return nullptr;
}
}
2018-08-03 08:15:28 +02:00
QskSkinHintTable::QskSkinHintTable()
: m_hints( nullptr )
, m_animatorCount( 0 )
, m_hasStates( false )
{
}
2018-08-03 08:15:28 +02:00
QskSkinHintTable::QskSkinHintTable( const QskSkinHintTable& other )
: m_hints( nullptr )
, m_animatorCount( other.m_animatorCount )
, m_hasStates( other.m_hasStates )
{
if ( other.m_hints )
2018-08-03 08:15:28 +02:00
m_hints = new HintMap( *( other.m_hints ) );
}
QskSkinHintTable::~QskSkinHintTable()
{
delete m_hints;
}
QskSkinHintTable& QskSkinHintTable::operator=( const QskSkinHintTable& other )
{
m_animatorCount = other.m_animatorCount;
m_hasStates = other.m_hasStates;
if ( other.m_hints )
{
if ( m_hints == nullptr )
m_hints = new HintMap();
*m_hints = *other.m_hints;
}
else
{
delete m_hints;
m_hints = nullptr;
}
return *this;
}
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::setHint( QskAspect::Aspect aspect, const QVariant& skinHint )
{
if ( m_hints == nullptr )
m_hints = new HintMap();
auto it = m_hints->find( aspect );
if ( it == m_hints->end() )
{
m_hints->emplace( aspect, skinHint );
if ( aspect.isAnimator() )
m_animatorCount++;
}
else if ( it->second != skinHint )
{
it->second = skinHint;
}
if ( aspect.state() )
m_hasStates = true;
}
bool QskSkinHintTable::removeHint( QskAspect::Aspect aspect )
{
if ( m_hints == nullptr )
return false;
const bool erased = m_hints->erase( aspect );
if ( erased )
{
if ( aspect.isAnimator() )
m_animatorCount--;
2018-08-03 08:15:28 +02:00
if ( m_hints->empty() )
{
delete m_hints;
m_hints = nullptr;
}
}
return erased;
}
QVariant QskSkinHintTable::takeHint( QskAspect::Aspect aspect )
{
if ( m_hints )
{
auto it = m_hints->find( aspect );
if ( it != m_hints->end() )
{
const auto value = it->second;
m_hints->erase( it );
if ( aspect.isAnimator() )
m_animatorCount--;
if ( m_hints->empty() )
{
delete m_hints;
m_hints = nullptr;
}
return value;
}
}
return QVariant();
}
void QskSkinHintTable::clear()
{
delete m_hints;
m_hints = nullptr;
m_animatorCount = 0;
}
const QVariant* QskSkinHintTable::resolvedHint(
QskAspect::Aspect aspect, QskAspect::Aspect* resolvedAspect ) const
{
if ( m_hints != nullptr )
return qskResolvedHint( aspect, *m_hints, resolvedAspect );
return nullptr;
}
QskAspect::Aspect QskSkinHintTable::resolvedAspect( QskAspect::Aspect aspect ) const
{
QskAspect::Aspect a;
if ( m_hints != nullptr )
qskResolvedHint( aspect, *m_hints, &a );
return a;
}
QskAspect::Aspect QskSkinHintTable::resolvedAnimator(
QskAspect::Aspect aspect, QskAnimationHint& hint ) const
{
if ( m_hints && m_animatorCount > 0 )
{
Q_FOREVER
{
auto it = m_hints->find( aspect );
if ( it != m_hints->cend() )
{
hint = it->second.value< QskAnimationHint >();
return aspect;
}
if ( const auto topState = aspect.topState() )
aspect.clearState( topState );
else
break;
}
}
return QskAspect::Aspect();
}