2017-07-21 18:21:34 +02:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "QskSkinnable.h"
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
#include "QskAnimationHint.h"
|
2021-10-20 07:50:25 +02:00
|
|
|
#include "QskArcMetrics.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
#include "QskAspect.h"
|
2018-08-03 08:15:28 +02:00
|
|
|
#include "QskColorFilter.h"
|
|
|
|
#include "QskControl.h"
|
|
|
|
#include "QskHintAnimator.h"
|
|
|
|
#include "QskMargins.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
#include "QskSetup.h"
|
|
|
|
#include "QskSkin.h"
|
2017-08-22 20:50:55 +02:00
|
|
|
#include "QskSkinHintTable.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
#include "QskSkinTransition.h"
|
2018-08-03 08:15:28 +02:00
|
|
|
#include "QskSkinlet.h"
|
2021-09-09 07:53:35 +02:00
|
|
|
#include "QskWindow.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-12-23 09:49:20 +01:00
|
|
|
#include "QskBoxShapeMetrics.h"
|
|
|
|
#include "QskBoxBorderMetrics.h"
|
|
|
|
#include "QskBoxBorderColors.h"
|
2022-01-04 13:44:53 +01:00
|
|
|
#include "QskBoxHints.h"
|
2020-12-23 09:49:20 +01:00
|
|
|
#include "QskGradient.h"
|
|
|
|
|
2018-07-19 14:10:48 +02:00
|
|
|
#include <qfont.h>
|
2021-12-24 16:17:49 +01:00
|
|
|
#include <qfontmetrics.h>
|
2021-08-04 15:06:04 +02:00
|
|
|
#include <map>
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
#define DEBUG_MAP 0
|
|
|
|
#define DEBUG_ANIMATOR 0
|
|
|
|
#define DEBUG_STATE 0
|
2017-09-06 10:22:59 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
static inline bool qskIsControl( const QskSkinnable* skinnable )
|
|
|
|
{
|
|
|
|
return skinnable->metaObject()->inherits( &QskControl::staticMetaObject );
|
|
|
|
}
|
|
|
|
|
2020-10-23 14:00:27 +02:00
|
|
|
static inline QVariant qskTypedNullValue( const QVariant& value )
|
|
|
|
{
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
|
|
|
const auto vType = static_cast< QMetaType >( value.userType() );
|
|
|
|
#else
|
|
|
|
const auto vType = value.userType();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return QVariant( vType, nullptr );
|
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
static inline bool qskSetFlag( QskSkinnable* skinnable,
|
2021-08-04 09:31:16 +02:00
|
|
|
const QskAspect aspect, int flag )
|
2020-12-21 09:57:57 +01:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return skinnable->setSkinHint( aspect | QskAspect::Flag, QVariant( flag ) );
|
2020-12-21 09:57:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline int qskFlag( const QskSkinnable* skinnable,
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, QskSkinHintStatus* status = nullptr )
|
2020-12-21 09:57:57 +01:00
|
|
|
{
|
2020-12-21 10:24:59 +01:00
|
|
|
return skinnable->effectiveSkinHint( aspect | QskAspect::Flag, status ).toInt();
|
2020-12-21 09:57:57 +01:00
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
static inline bool qskSetMetric( QskSkinnable* skinnable,
|
2021-08-04 09:31:16 +02:00
|
|
|
const QskAspect aspect, const QVariant& metric )
|
2020-12-21 09:57:57 +01:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return skinnable->setSkinHint( aspect | QskAspect::Metric, metric );
|
2020-12-21 09:57:57 +01:00
|
|
|
}
|
|
|
|
|
2021-12-29 15:55:44 +01:00
|
|
|
static inline bool qskMoveMetric( QskSkinnable* skinnable,
|
|
|
|
const QskAspect aspect, const QVariant& metric )
|
|
|
|
{
|
|
|
|
return skinnable->moveSkinHint( aspect | QskAspect::Metric, metric );
|
|
|
|
}
|
|
|
|
|
2020-12-21 09:57:57 +01:00
|
|
|
template< typename T >
|
2020-12-27 12:06:12 +01:00
|
|
|
static inline bool qskSetMetric( QskSkinnable* skinnable,
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect aspect, const T& metric )
|
2020-12-21 09:57:57 +01:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetMetric( skinnable, aspect, QVariant::fromValue( metric ) );
|
2020-12-21 09:57:57 +01:00
|
|
|
}
|
|
|
|
|
2021-12-29 15:55:44 +01:00
|
|
|
template< typename T >
|
|
|
|
static inline bool qskMoveMetric( QskSkinnable* skinnable,
|
|
|
|
QskAspect aspect, const T& metric )
|
|
|
|
{
|
|
|
|
return qskMoveMetric( skinnable, aspect, QVariant::fromValue( metric ) );
|
|
|
|
}
|
|
|
|
|
2020-12-21 09:57:57 +01:00
|
|
|
template< typename T >
|
|
|
|
static inline T qskMetric( const QskSkinnable* skinnable,
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect aspect, QskSkinHintStatus* status = nullptr )
|
2020-12-21 09:57:57 +01:00
|
|
|
{
|
2020-12-21 10:24:59 +01:00
|
|
|
return skinnable->effectiveSkinHint(
|
2020-12-21 09:57:57 +01:00
|
|
|
aspect | QskAspect::Metric, status ).value< T >();
|
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
static inline bool qskSetColor( QskSkinnable* skinnable,
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, const QVariant& color )
|
2020-12-21 09:57:57 +01:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return skinnable->setSkinHint( aspect | QskAspect::Color, color );
|
2020-12-21 09:57:57 +01:00
|
|
|
}
|
|
|
|
|
2021-12-29 15:55:44 +01:00
|
|
|
static inline bool qskMoveColor( QskSkinnable* skinnable,
|
|
|
|
const QskAspect aspect, const QVariant& color )
|
|
|
|
{
|
|
|
|
return skinnable->moveSkinHint( aspect | QskAspect::Color, color );
|
|
|
|
}
|
|
|
|
|
2020-12-21 09:57:57 +01:00
|
|
|
template< typename T >
|
2020-12-27 12:06:12 +01:00
|
|
|
static inline bool qskSetColor( QskSkinnable* skinnable,
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, const T& color )
|
2020-12-21 09:57:57 +01:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetColor( skinnable, aspect, QVariant::fromValue( color ) );
|
2020-12-21 09:57:57 +01:00
|
|
|
}
|
|
|
|
|
2021-12-29 15:55:44 +01:00
|
|
|
template< typename T >
|
|
|
|
static inline bool qskMoveColor( QskSkinnable* skinnable,
|
|
|
|
const QskAspect aspect, const T& color )
|
|
|
|
{
|
|
|
|
return qskMoveColor( skinnable, aspect, QVariant::fromValue( color ) );
|
|
|
|
}
|
|
|
|
|
2020-12-21 09:57:57 +01:00
|
|
|
template< typename T >
|
|
|
|
static inline T qskColor( const QskSkinnable* skinnable,
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect aspect, QskSkinHintStatus* status = nullptr )
|
2020-12-21 09:57:57 +01:00
|
|
|
{
|
2020-12-21 10:24:59 +01:00
|
|
|
return skinnable->effectiveSkinHint(
|
2020-12-21 09:57:57 +01:00
|
|
|
aspect | QskAspect::Color, status ).value< T >();
|
|
|
|
}
|
|
|
|
|
2020-12-27 16:31:07 +01:00
|
|
|
static inline void qskTriggerUpdates( QskAspect aspect, QskControl* control )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
To put the hint into effect we have to call the usual suspects:
|
|
|
|
|
|
|
|
- resetImplicitSize
|
|
|
|
- polish
|
|
|
|
- update
|
|
|
|
|
|
|
|
The following code decides about these calls based on type/primitive
|
|
|
|
of the aspect. It can be expected, that it results in more calls
|
|
|
|
than what would be mandatory and in rare cases we might even miss necessary
|
|
|
|
calls. This has to be fixed by doing the call manually in the specific
|
|
|
|
controls.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ( control == nullptr || aspect.isAnimator() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool maybeLayout = false;
|
|
|
|
|
|
|
|
switch( aspect.type() )
|
|
|
|
{
|
|
|
|
using A = QskAspect;
|
|
|
|
|
|
|
|
case A::Metric:
|
|
|
|
{
|
|
|
|
if ( aspect.metricPrimitive() != A::Position )
|
|
|
|
{
|
|
|
|
control->resetImplicitSize();
|
|
|
|
maybeLayout = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case A::Color:
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case A::Flag:
|
|
|
|
{
|
|
|
|
switch( aspect.flagPrimitive() )
|
|
|
|
{
|
|
|
|
case A::GraphicRole:
|
|
|
|
case A::FontRole:
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case A::Alignment:
|
|
|
|
{
|
|
|
|
maybeLayout = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
control->resetImplicitSize();
|
|
|
|
maybeLayout = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
control->update(); // always
|
|
|
|
|
|
|
|
if ( maybeLayout && control->hasChildItems() )
|
|
|
|
{
|
|
|
|
if ( control->polishOnResize() || control->autoLayoutChildren() )
|
|
|
|
control->polish();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-21 07:30:32 +01:00
|
|
|
static inline QskAspect qskSubstitutedAspect(
|
|
|
|
const QskSkinnable* skinnable, QskAspect aspect )
|
|
|
|
{
|
2022-01-10 08:47:27 +01:00
|
|
|
#if 0
|
2021-09-14 13:05:56 +02:00
|
|
|
if ( aspect.hasStates() )
|
2021-01-21 07:30:32 +01:00
|
|
|
{
|
|
|
|
qWarning() << "QskSkinnable::(re)setSkinHint: setting hints with states "
|
|
|
|
"is discouraged - use QskSkinTableEditor if you are "
|
|
|
|
"sure, that you need this.";
|
|
|
|
|
|
|
|
qWarning() << "QskAspect:" << aspect.stateless()
|
2021-09-14 13:05:56 +02:00
|
|
|
<< skinnable->skinStatesAsPrintable( aspect.states() );
|
2021-01-21 07:30:32 +01:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
aspect.clearStates();
|
|
|
|
#endif
|
|
|
|
}
|
2022-01-10 08:47:27 +01:00
|
|
|
#endif
|
2021-01-21 07:30:32 +01:00
|
|
|
|
|
|
|
aspect.setSubControl( skinnable->effectiveSubcontrol( aspect.subControl() ) );
|
|
|
|
return aspect;
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
class QskSkinnable::PrivateData
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
public:
|
2017-07-21 18:21:34 +02:00
|
|
|
~PrivateData()
|
|
|
|
{
|
2017-12-08 13:56:35 +01:00
|
|
|
if ( hasLocalSkinlet )
|
|
|
|
{
|
|
|
|
if ( skinlet && skinlet->isOwnedBySkinnable() )
|
|
|
|
delete skinlet;
|
|
|
|
}
|
2021-08-30 12:39:16 +02:00
|
|
|
|
|
|
|
delete subcontrolProxies;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2017-08-22 20:50:55 +02:00
|
|
|
QskSkinHintTable hintTable;
|
2017-07-21 18:21:34 +02:00
|
|
|
QskHintAnimatorTable animators;
|
|
|
|
|
2021-08-04 15:06:04 +02:00
|
|
|
typedef std::map< QskAspect::Subcontrol, QskAspect::Subcontrol > ProxyMap;
|
|
|
|
ProxyMap* subcontrolProxies = nullptr;
|
|
|
|
|
|
|
|
const QskSkinlet* skinlet = nullptr;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2021-09-14 13:27:22 +02:00
|
|
|
QskAspect::States skinStates;
|
2021-08-04 15:06:04 +02:00
|
|
|
bool hasLocalSkinlet = false;
|
2017-07-21 18:21:34 +02:00
|
|
|
};
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskSkinnable::QskSkinnable()
|
|
|
|
: m_data( new PrivateData() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QskSkinnable::~QskSkinnable()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskSkinnable::setSkinlet( const QskSkinlet* skinlet )
|
|
|
|
{
|
|
|
|
if ( skinlet == m_data->skinlet )
|
|
|
|
{
|
|
|
|
if ( skinlet )
|
|
|
|
{
|
|
|
|
// now we don't depend on global skin changes anymore
|
|
|
|
m_data->hasLocalSkinlet = true;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( m_data->skinlet && m_data->skinlet->isOwnedBySkinnable() )
|
|
|
|
delete m_data->skinlet;
|
|
|
|
|
|
|
|
m_data->skinlet = skinlet;
|
|
|
|
m_data->hasLocalSkinlet = ( skinlet != nullptr );
|
|
|
|
|
2021-02-11 12:45:17 +01:00
|
|
|
if ( auto control = owningControl() )
|
|
|
|
{
|
|
|
|
control->resetImplicitSize();
|
|
|
|
control->polish();
|
|
|
|
|
|
|
|
if ( control->flags() & QQuickItem::ItemHasContents )
|
|
|
|
control->update();
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const QskSkinlet* QskSkinnable::skinlet() const
|
|
|
|
{
|
|
|
|
return m_data->hasLocalSkinlet ? m_data->skinlet : nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const QskSkinlet* QskSkinnable::effectiveSkinlet() const
|
|
|
|
{
|
|
|
|
if ( m_data->skinlet == nullptr )
|
|
|
|
{
|
2021-09-09 07:53:35 +02:00
|
|
|
m_data->skinlet = effectiveSkin()->skinlet( metaObject() );
|
2017-07-21 18:21:34 +02:00
|
|
|
m_data->hasLocalSkinlet = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_data->skinlet;
|
|
|
|
}
|
|
|
|
|
2021-08-04 15:06:04 +02:00
|
|
|
void QskSkinnable::setSubcontrolProxy(
|
|
|
|
QskAspect::Subcontrol subControl, QskAspect::Subcontrol proxy )
|
|
|
|
{
|
|
|
|
if ( subControl == QskAspect::Control )
|
|
|
|
return; // nonsense, we ignore this
|
|
|
|
|
|
|
|
if ( proxy == QskAspect::Control || subControl == proxy )
|
|
|
|
{
|
|
|
|
resetSubcontrolProxy( subControl );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( m_data->subcontrolProxies == nullptr )
|
|
|
|
m_data->subcontrolProxies = new PrivateData::ProxyMap();
|
|
|
|
|
2021-08-04 15:06:44 +02:00
|
|
|
( *m_data->subcontrolProxies )[ subControl ] = proxy;
|
2021-08-04 15:06:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskSkinnable::resetSubcontrolProxy( QskAspect::Subcontrol subcontrol )
|
|
|
|
{
|
|
|
|
if ( auto& proxies = m_data->subcontrolProxies )
|
|
|
|
{
|
|
|
|
auto it = proxies->find( subcontrol );
|
|
|
|
if ( it != proxies->end() )
|
|
|
|
{
|
|
|
|
proxies->erase( it );
|
|
|
|
if ( proxies->empty() )
|
|
|
|
{
|
|
|
|
delete proxies;
|
|
|
|
proxies = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QskAspect::Subcontrol QskSkinnable::subcontrolProxy( QskAspect::Subcontrol subControl ) const
|
|
|
|
{
|
|
|
|
if ( const auto proxies = m_data->subcontrolProxies )
|
|
|
|
{
|
|
|
|
auto it = proxies->find( subControl );
|
|
|
|
if ( it != proxies->end() )
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
return QskAspect::Control;
|
|
|
|
}
|
|
|
|
|
2018-03-22 11:22:13 +01:00
|
|
|
QskSkinHintTable& QskSkinnable::hintTable()
|
2017-08-22 20:50:55 +02:00
|
|
|
{
|
|
|
|
return m_data->hintTable;
|
|
|
|
}
|
|
|
|
|
2018-03-22 11:22:13 +01:00
|
|
|
const QskSkinHintTable& QskSkinnable::hintTable() const
|
2017-08-22 20:50:55 +02:00
|
|
|
{
|
|
|
|
return m_data->hintTable;
|
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setFlagHint( const QskAspect aspect, int flag )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetFlag( this, aspect, flag );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
int QskSkinnable::flagHint( const QskAspect aspect ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-21 10:24:59 +01:00
|
|
|
return effectiveSkinHint( aspect ).toInt();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setAlignmentHint( const QskAspect aspect, Qt::Alignment alignment )
|
2020-12-15 07:21:12 +01:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetFlag( this, aspect | QskAspect::Alignment, alignment );
|
2020-12-15 07:21:12 +01:00
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
bool QskSkinnable::resetAlignmentHint( const QskAspect aspect )
|
2020-12-15 11:01:00 +01:00
|
|
|
{
|
|
|
|
return resetFlagHint( aspect | QskAspect::Alignment );
|
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setColor( const QskAspect aspect, const QColor& color )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetColor( this, aspect, color );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setColor( const QskAspect aspect, Qt::GlobalColor color )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetColor( this, aspect, QColor( color ) );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setColor( const QskAspect aspect, QRgb rgb )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetColor( this, aspect, QColor::fromRgba( rgb ) );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2021-12-29 15:55:44 +01:00
|
|
|
bool QskSkinnable::moveColor( const QskAspect aspect, const QColor& color )
|
|
|
|
{
|
|
|
|
return qskMoveColor( this, aspect, color );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskSkinnable::moveColor( const QskAspect aspect, Qt::GlobalColor color )
|
|
|
|
{
|
|
|
|
return qskMoveColor( this, aspect, QColor( color ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskSkinnable::moveColor( const QskAspect aspect, QRgb rgb )
|
|
|
|
{
|
|
|
|
return qskMoveColor( this, aspect, QColor::fromRgba( rgb ) );
|
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
QColor QskSkinnable::color( const QskAspect aspect, QskSkinHintStatus* status ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return qskColor< QColor >( this, aspect, status );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setMetric( const QskAspect aspect, qreal metric )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetMetric( this, aspect, metric );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2021-12-29 15:55:44 +01:00
|
|
|
bool QskSkinnable::moveMetric( QskAspect aspect, qreal metric )
|
|
|
|
{
|
|
|
|
return qskMoveMetric( this, aspect, metric );
|
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
qreal QskSkinnable::metric( const QskAspect aspect, QskSkinHintStatus* status ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return qskMetric< qreal >( this, aspect, status );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2021-12-29 15:55:44 +01:00
|
|
|
bool QskSkinnable::setPositionHint( QskAspect aspect, qreal position )
|
|
|
|
{
|
|
|
|
return qskSetMetric( this, aspect | QskAspect::Position, position );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskSkinnable::movePositionHint( QskAspect aspect, qreal position )
|
|
|
|
{
|
|
|
|
return qskMoveMetric( this, aspect | QskAspect::Position, position );
|
|
|
|
}
|
|
|
|
|
2021-12-29 16:21:33 +01:00
|
|
|
bool QskSkinnable::movePositionHint( QskAspect aspect, qreal from, qreal to )
|
|
|
|
{
|
|
|
|
return moveSkinHint( aspect | QskAspect::Metric | QskAspect::Position,
|
|
|
|
QVariant::fromValue( from ), QVariant::fromValue( to ) );
|
|
|
|
}
|
|
|
|
|
2021-12-29 15:55:44 +01:00
|
|
|
bool QskSkinnable::resetPositionHint( QskAspect aspect )
|
|
|
|
{
|
|
|
|
return resetMetric( aspect | QskAspect::Position );
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskSkinnable::positionHint( QskAspect aspect, QskSkinHintStatus* status ) const
|
|
|
|
{
|
|
|
|
return qskMetric< qreal >( this, aspect | QskAspect::Position, status );
|
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setStrutSizeHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, qreal width, qreal height )
|
2020-12-16 12:49:24 +01:00
|
|
|
{
|
2021-01-21 07:30:32 +01:00
|
|
|
return qskSetMetric( this, aspect | QskAspect::StrutSize, QSizeF( width, height ) );
|
2020-12-16 12:49:24 +01:00
|
|
|
}
|
|
|
|
|
2021-02-22 17:15:37 +01:00
|
|
|
bool QskSkinnable::setStrutSizeHint( const QskAspect aspect, const QSizeF& size )
|
2020-12-16 12:49:24 +01:00
|
|
|
{
|
2021-02-22 17:15:37 +01:00
|
|
|
return qskSetMetric( this, aspect | QskAspect::StrutSize, size );
|
2020-12-16 12:49:24 +01:00
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
bool QskSkinnable::resetStrutSizeHint( const QskAspect aspect )
|
2020-12-17 08:53:00 +01:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return resetMetric( aspect | QskAspect::StrutSize );
|
2020-12-17 08:53:00 +01:00
|
|
|
}
|
|
|
|
|
2020-12-16 12:49:24 +01:00
|
|
|
QSizeF QskSkinnable::strutSizeHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, QskSkinHintStatus* status ) const
|
2020-12-16 12:49:24 +01:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return qskMetric< QSizeF >( this, aspect | QskAspect::StrutSize, status );
|
2020-12-16 12:49:24 +01:00
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setMarginHint( const QskAspect aspect, qreal margins )
|
2020-12-15 07:21:12 +01:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetMetric( this, aspect | QskAspect::Margin, QskMargins( margins ) );
|
2020-12-15 07:21:12 +01:00
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setMarginHint( const QskAspect aspect, const QMarginsF& margins )
|
2020-12-15 07:21:12 +01:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetMetric( this, aspect | QskAspect::Margin, QskMargins( margins ) );
|
2020-12-15 07:21:12 +01:00
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
bool QskSkinnable::resetMarginHint( const QskAspect aspect )
|
2020-12-15 11:01:00 +01:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return resetMetric( aspect | QskAspect::Margin );
|
2020-12-15 11:01:00 +01:00
|
|
|
}
|
|
|
|
|
2020-12-15 07:21:12 +01:00
|
|
|
QMarginsF QskSkinnable::marginHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, QskSkinHintStatus* status ) const
|
2020-12-15 07:21:12 +01:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return qskMetric< QskMargins >( this, aspect | QskAspect::Margin, status );
|
2020-12-15 07:21:12 +01:00
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setPaddingHint( const QskAspect aspect, qreal padding )
|
2017-10-18 20:00:06 +02:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetMetric( this, aspect | QskAspect::Padding, QskMargins( padding ) );
|
2017-10-18 20:00:06 +02:00
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setPaddingHint( const QskAspect aspect, const QMarginsF& padding )
|
2017-08-23 14:53:29 +02:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetMetric( this, aspect | QskAspect::Padding, QskMargins( padding ) );
|
2017-08-23 14:53:29 +02:00
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
bool QskSkinnable::resetPaddingHint( const QskAspect aspect )
|
2020-12-15 11:01:00 +01:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return resetMetric( aspect | QskAspect::Padding );
|
2020-12-15 11:01:00 +01:00
|
|
|
}
|
|
|
|
|
2020-12-15 07:21:12 +01:00
|
|
|
QMarginsF QskSkinnable::paddingHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, QskSkinHintStatus* status ) const
|
2017-08-23 14:53:29 +02:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return qskMetric< QskMargins >( this, aspect | QskAspect::Padding, status );
|
2017-08-23 14:53:29 +02:00
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setGradientHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, const QskGradient& gradient )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetColor( this, aspect, gradient );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QskGradient QskSkinnable::gradientHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, QskSkinHintStatus* status ) const
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return qskColor< QskGradient >( this, aspect, status );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setBoxShapeHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, const QskBoxShapeMetrics& shape )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetMetric( this, aspect | QskAspect::Shape, shape );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
bool QskSkinnable::resetBoxShapeHint( const QskAspect aspect )
|
2020-12-15 11:01:00 +01:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return resetMetric( aspect | QskAspect::Shape );
|
2020-12-15 11:01:00 +01:00
|
|
|
}
|
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
QskBoxShapeMetrics QskSkinnable::boxShapeHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, QskSkinHintStatus* status ) const
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return qskMetric< QskBoxShapeMetrics >(
|
|
|
|
this, aspect | QskAspect::Shape, status );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setBoxBorderMetricsHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, const QskBoxBorderMetrics& border )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetMetric( this, aspect | QskAspect::Border, border );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
bool QskSkinnable::resetBoxBorderMetricsHint( const QskAspect aspect )
|
2020-12-15 11:01:00 +01:00
|
|
|
{
|
2020-12-21 10:24:59 +01:00
|
|
|
return resetMetric( aspect | QskAspect::Border );
|
2020-12-15 11:01:00 +01:00
|
|
|
}
|
|
|
|
|
2017-10-18 20:00:06 +02:00
|
|
|
QskBoxBorderMetrics QskSkinnable::boxBorderMetricsHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, QskSkinHintStatus* status ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return qskMetric< QskBoxBorderMetrics >(
|
|
|
|
this, aspect | QskAspect::Border, status );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setBoxBorderColorsHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, const QskBoxBorderColors& colors )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetColor( this, aspect | QskAspect::Border, colors );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
bool QskSkinnable::resetBoxBorderColorsHint( const QskAspect aspect )
|
2020-12-15 11:01:00 +01:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return resetColor( aspect | QskAspect::Border );
|
2020-12-15 11:01:00 +01:00
|
|
|
}
|
|
|
|
|
2017-10-18 20:00:06 +02:00
|
|
|
QskBoxBorderColors QskSkinnable::boxBorderColorsHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, QskSkinHintStatus* status ) const
|
2018-03-22 11:22:13 +01:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return qskColor< QskBoxBorderColors >(
|
|
|
|
this, aspect | QskAspect::Border, status );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2022-01-04 13:44:53 +01:00
|
|
|
QskBoxHints QskSkinnable::boxHints( QskAspect aspect ) const
|
|
|
|
{
|
|
|
|
return QskBoxHints(
|
|
|
|
boxShapeHint( aspect ), boxBorderMetricsHint( aspect ),
|
|
|
|
boxBorderColorsHint( aspect ), gradientHint( aspect ) );
|
|
|
|
}
|
|
|
|
|
2021-10-20 07:50:25 +02:00
|
|
|
bool QskSkinnable::setArcMetricsHint(
|
|
|
|
const QskAspect aspect, const QskArcMetrics& arc )
|
|
|
|
{
|
|
|
|
return qskSetMetric( this, aspect | QskAspect::Shape, arc );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskSkinnable::resetArcMetricsHint( const QskAspect aspect )
|
|
|
|
{
|
|
|
|
return resetMetric( aspect | QskAspect::Shape );
|
|
|
|
}
|
|
|
|
|
|
|
|
QskArcMetrics QskSkinnable::arcMetricsHint(
|
|
|
|
const QskAspect aspect, QskSkinHintStatus* status ) const
|
|
|
|
{
|
|
|
|
return qskMetric< QskArcMetrics >(
|
|
|
|
this, aspect | QskAspect::Shape, status );
|
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setSpacingHint( const QskAspect aspect, qreal spacing )
|
2020-12-15 07:21:12 +01:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetMetric( this, aspect | QskAspect::Spacing, spacing );
|
2020-12-15 07:21:12 +01:00
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
bool QskSkinnable::resetSpacingHint( const QskAspect aspect )
|
2020-12-15 11:01:00 +01:00
|
|
|
{
|
|
|
|
return resetMetric( aspect | QskAspect::Spacing );
|
|
|
|
}
|
|
|
|
|
2020-12-15 07:21:12 +01:00
|
|
|
qreal QskSkinnable::spacingHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, QskSkinHintStatus* status ) const
|
2020-12-15 07:21:12 +01:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return qskMetric< qreal >( this, aspect | QskAspect::Spacing, status );
|
2020-12-15 07:21:12 +01:00
|
|
|
}
|
|
|
|
|
2020-12-27 16:19:01 +01:00
|
|
|
bool QskSkinnable::setFontRoleHint( const QskAspect aspect, int role )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetFlag( this, aspect | QskAspect::FontRole, role );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-12-27 16:19:01 +01:00
|
|
|
bool QskSkinnable::resetFontRoleHint( const QskAspect aspect )
|
|
|
|
{
|
|
|
|
return resetFlagHint( aspect | QskAspect::FontRole );
|
|
|
|
}
|
|
|
|
|
|
|
|
int QskSkinnable::fontRoleHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, QskSkinHintStatus* status ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return qskFlag( this, aspect | QskAspect::FontRole, status );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
QFont QskSkinnable::effectiveFont( const QskAspect aspect ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-27 16:19:01 +01:00
|
|
|
return effectiveSkin()->font( fontRoleHint( aspect ) );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2021-12-24 16:17:49 +01:00
|
|
|
qreal QskSkinnable::effectiveFontHeight( const QskAspect aspect ) const
|
|
|
|
{
|
|
|
|
const QFontMetricsF fm( effectiveFont( aspect ) );
|
|
|
|
return fm.height();
|
|
|
|
}
|
|
|
|
|
2020-12-27 16:19:01 +01:00
|
|
|
bool QskSkinnable::setGraphicRoleHint( const QskAspect aspect, int role )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-27 12:06:12 +01:00
|
|
|
return qskSetFlag( this, aspect | QskAspect::GraphicRole, role );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-12-27 16:19:01 +01:00
|
|
|
bool QskSkinnable::resetGraphicRoleHint( const QskAspect aspect )
|
|
|
|
{
|
|
|
|
return resetFlagHint( aspect | QskAspect::GraphicRole );
|
|
|
|
}
|
|
|
|
|
|
|
|
int QskSkinnable::graphicRoleHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
const QskAspect aspect, QskSkinHintStatus* status ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
return qskFlag( this, aspect | QskAspect::GraphicRole, status );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
QskColorFilter QskSkinnable::effectiveGraphicFilter( QskAspect aspect ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
aspect.setSubControl( effectiveSubcontrol( aspect.subControl() ) );
|
2017-10-17 17:34:00 +02:00
|
|
|
aspect.setPlacement( effectivePlacement() );
|
2017-07-21 18:21:34 +02:00
|
|
|
aspect = aspect | QskAspect::GraphicRole;
|
|
|
|
|
|
|
|
QskSkinHintStatus status;
|
|
|
|
|
2021-09-14 13:05:56 +02:00
|
|
|
const auto hint = storedHint( aspect | skinStates(), &status );
|
2017-07-21 18:21:34 +02:00
|
|
|
if ( status.isValid() )
|
|
|
|
{
|
|
|
|
// we need to know about how the aspect gets resolved
|
|
|
|
// before checking for animators
|
|
|
|
|
|
|
|
aspect.setSubControl( status.aspect.subControl() );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !aspect.isAnimator() )
|
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
auto v = animatedValue( aspect, nullptr );
|
2017-07-21 18:21:34 +02:00
|
|
|
if ( v.canConvert< QskColorFilter >() )
|
|
|
|
return v.value< QskColorFilter >();
|
2018-03-22 11:22:13 +01:00
|
|
|
|
2019-02-03 12:48:43 +01:00
|
|
|
if ( auto control = owningControl() )
|
2018-03-22 11:22:13 +01:00
|
|
|
{
|
2019-02-03 12:48:43 +01:00
|
|
|
v = QskSkinTransition::animatedGraphicFilter(
|
2021-08-04 09:31:16 +02:00
|
|
|
control->window(), hint.toInt() );
|
2018-03-22 11:22:13 +01:00
|
|
|
|
|
|
|
if ( v.canConvert< QskColorFilter >() )
|
|
|
|
{
|
2019-02-03 12:48:43 +01:00
|
|
|
/*
|
|
|
|
As it is hard to find out which controls depend
|
|
|
|
on the animated graphic filters we reschedule
|
|
|
|
our updates here.
|
|
|
|
*/
|
|
|
|
control->update();
|
2018-03-22 11:22:13 +01:00
|
|
|
return v.value< QskColorFilter >();
|
|
|
|
}
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return effectiveSkin()->graphicFilter( hint.toInt() );
|
|
|
|
}
|
|
|
|
|
2020-12-27 12:06:12 +01:00
|
|
|
bool QskSkinnable::setAnimationHint(
|
2021-02-16 12:19:05 +01:00
|
|
|
QskAspect aspect, QskAnimationHint hint )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-23 09:38:10 +01:00
|
|
|
aspect.setSubControl( effectiveSubcontrol( aspect.subControl() ) );
|
2021-02-16 12:19:05 +01:00
|
|
|
return m_data->hintTable.setAnimation( aspect, hint );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-12-21 09:57:57 +01:00
|
|
|
QskAnimationHint QskSkinnable::animationHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect aspect, QskSkinHintStatus* status ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
aspect.setAnimator( true );
|
2020-12-21 10:24:59 +01:00
|
|
|
return effectiveSkinHint( aspect, status ).value< QskAnimationHint >();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2021-12-29 15:55:44 +01:00
|
|
|
bool QskSkinnable::hasAnimationHint( QskAspect aspect ) const
|
|
|
|
{
|
|
|
|
return animationHint( aspect ).isValid();
|
|
|
|
}
|
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
QskAnimationHint QskSkinnable::effectiveAnimation(
|
2018-03-22 11:22:13 +01:00
|
|
|
QskAspect::Type type, QskAspect::Subcontrol subControl,
|
2021-09-14 13:05:56 +02:00
|
|
|
QskAspect::States states, QskSkinHintStatus* status ) const
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
2021-02-16 12:19:05 +01:00
|
|
|
#if 0
|
|
|
|
// TODO ...
|
|
|
|
subControl = effectiveSubcontrol( aspect.subControl() );
|
|
|
|
#endif
|
|
|
|
|
2021-09-14 13:05:56 +02:00
|
|
|
auto aspect = subControl | type | states;
|
2017-10-17 17:34:00 +02:00
|
|
|
aspect.setAnimator( true );
|
|
|
|
|
|
|
|
QskAnimationHint hint;
|
|
|
|
|
|
|
|
const auto a = m_data->hintTable.resolvedAnimator( aspect, hint );
|
|
|
|
if ( a.isAnimator() )
|
|
|
|
{
|
|
|
|
if ( status )
|
|
|
|
{
|
|
|
|
status->source = QskSkinHintStatus::Skinnable;
|
|
|
|
status->aspect = a;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hint;
|
|
|
|
}
|
|
|
|
|
2019-04-19 17:04:36 +02:00
|
|
|
if ( auto skin = effectiveSkin() )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
|
|
|
const auto a = skin->hintTable().resolvedAnimator( aspect, hint );
|
|
|
|
if ( a.isAnimator() )
|
|
|
|
{
|
|
|
|
if ( status )
|
|
|
|
{
|
|
|
|
status->source = QskSkinHintStatus::Skin;
|
|
|
|
status->aspect = a;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hint;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( status )
|
|
|
|
{
|
|
|
|
status->source = QskSkinHintStatus::NoSource;
|
2020-12-21 16:06:58 +01:00
|
|
|
status->aspect = QskAspect();
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return hint;
|
|
|
|
}
|
|
|
|
|
2020-12-27 16:31:07 +01:00
|
|
|
bool QskSkinnable::setSkinHint( QskAspect aspect, const QVariant& hint )
|
2019-03-19 17:36:12 +01:00
|
|
|
{
|
2020-12-27 16:31:07 +01:00
|
|
|
aspect = qskSubstitutedAspect( this, aspect );
|
2019-12-14 13:34:30 +01:00
|
|
|
|
2020-12-27 16:31:07 +01:00
|
|
|
if ( m_data->hintTable.setHint( aspect, hint ) )
|
|
|
|
{
|
|
|
|
qskTriggerUpdates( aspect, owningControl() );
|
|
|
|
return true;
|
|
|
|
}
|
2019-12-14 16:40:18 +01:00
|
|
|
|
2020-12-27 16:31:07 +01:00
|
|
|
return false;
|
|
|
|
}
|
2020-08-09 11:50:34 +02:00
|
|
|
|
2020-12-27 16:31:07 +01:00
|
|
|
bool QskSkinnable::resetSkinHint( QskAspect aspect )
|
|
|
|
{
|
|
|
|
aspect = qskSubstitutedAspect( this, aspect );
|
2019-12-14 16:40:18 +01:00
|
|
|
|
2020-12-27 16:31:07 +01:00
|
|
|
if ( m_data->hintTable.removeHint( aspect ) )
|
|
|
|
{
|
|
|
|
qskTriggerUpdates( aspect, owningControl() );
|
|
|
|
return true;
|
|
|
|
}
|
2019-12-14 16:40:18 +01:00
|
|
|
|
2020-12-27 16:31:07 +01:00
|
|
|
return false;
|
2019-03-19 17:36:12 +01:00
|
|
|
}
|
|
|
|
|
2020-12-21 10:24:59 +01:00
|
|
|
QVariant QskSkinnable::effectiveSkinHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect aspect, QskSkinHintStatus* status ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-21 09:57:57 +01:00
|
|
|
aspect.setSubControl( effectiveSubcontrol( aspect.subControl() ) );
|
2022-02-08 09:00:13 +01:00
|
|
|
|
|
|
|
if ( aspect.placement() == QskAspect::NoPlacement )
|
|
|
|
aspect.setPlacement( effectivePlacement() );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
if ( aspect.isAnimator() )
|
2017-08-22 19:47:06 +02:00
|
|
|
return storedHint( aspect, status );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-12-20 16:10:24 +01:00
|
|
|
const auto v = animatedValue( aspect, status );
|
2017-07-21 18:21:34 +02:00
|
|
|
if ( v.isValid() )
|
|
|
|
return v;
|
|
|
|
|
2021-09-14 13:05:56 +02:00
|
|
|
if ( !aspect.hasStates() )
|
|
|
|
aspect.setStates( skinStates() );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-08-22 19:47:06 +02:00
|
|
|
return storedHint( aspect, status );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
QskSkinHintStatus QskSkinnable::hintStatus( QskAspect aspect ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
QskSkinHintStatus status;
|
|
|
|
|
2020-12-21 10:24:59 +01:00
|
|
|
( void ) effectiveSkinHint( aspect, &status );
|
2017-07-21 18:21:34 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2021-12-29 15:55:44 +01:00
|
|
|
bool QskSkinnable::moveSkinHint( QskAspect aspect,
|
|
|
|
const QVariant& oldValue, const QVariant& newValue )
|
|
|
|
{
|
|
|
|
if ( aspect.isAnimator() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const bool ok = setSkinHint( aspect, newValue );
|
|
|
|
|
|
|
|
if ( ok && oldValue.isValid() && newValue.isValid() )
|
|
|
|
{
|
2021-12-29 17:19:19 +01:00
|
|
|
const auto animation = animationHint( aspect );
|
2021-12-29 15:55:44 +01:00
|
|
|
if ( animation.isValid() )
|
|
|
|
{
|
|
|
|
if ( newValue != oldValue )
|
|
|
|
startTransition( aspect, animation, oldValue, newValue );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskSkinnable::moveSkinHint( QskAspect aspect, const QVariant& value )
|
|
|
|
{
|
|
|
|
return moveSkinHint( aspect, effectiveSkinHint( aspect ), value );
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
QVariant QskSkinnable::animatedValue(
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect aspect, QskSkinHintStatus* status ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
QVariant v;
|
|
|
|
|
2021-09-14 13:05:56 +02:00
|
|
|
if ( !aspect.hasStates() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
The local animators were invented to be stateless
|
|
|
|
and we never have an aspect with a state here.
|
|
|
|
But that might change ...
|
|
|
|
*/
|
|
|
|
|
|
|
|
v = m_data->animators.currentValue( aspect );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !v.isValid() )
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( QskSkinTransition::isRunning() &&
|
|
|
|
!m_data->hintTable.hasHint( aspect ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
Next we check for values from the skin. Those
|
|
|
|
animators are usually from global skin/color changes
|
|
|
|
and are state aware
|
|
|
|
*/
|
|
|
|
|
2019-02-03 12:48:43 +01:00
|
|
|
if ( const auto control = owningControl() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2021-09-14 13:05:56 +02:00
|
|
|
if ( !aspect.hasStates() )
|
|
|
|
aspect.setStates( skinStates() );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2019-04-23 11:34:34 +02:00
|
|
|
const auto a = aspect;
|
2019-04-19 17:04:36 +02:00
|
|
|
|
2019-02-03 12:48:43 +01:00
|
|
|
Q_FOREVER
|
|
|
|
{
|
2019-04-23 11:34:34 +02:00
|
|
|
v = QskSkinTransition::animatedHint( control->window(), aspect );
|
2019-04-19 17:04:36 +02:00
|
|
|
|
2019-04-23 11:34:34 +02:00
|
|
|
if ( !v.isValid() )
|
|
|
|
{
|
|
|
|
if ( const auto topState = aspect.topState() )
|
|
|
|
{
|
|
|
|
aspect.clearState( aspect.topState() );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( aspect.placement() )
|
|
|
|
{
|
|
|
|
// clear the placement bits and restart
|
|
|
|
aspect = a;
|
|
|
|
aspect.setPlacement( QskAspect::NoPlacement );
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-19 17:04:36 +02:00
|
|
|
}
|
|
|
|
|
2019-04-23 11:34:34 +02:00
|
|
|
break;
|
2019-02-03 12:48:43 +01:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( status && v.isValid() )
|
|
|
|
{
|
|
|
|
status->source = QskSkinHintStatus::Animator;
|
|
|
|
status->aspect = aspect;
|
|
|
|
}
|
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2017-08-22 19:47:06 +02:00
|
|
|
const QVariant& QskSkinnable::storedHint(
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect aspect, QskSkinHintStatus* status ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-03-19 14:10:50 +01:00
|
|
|
const auto skin = effectiveSkin();
|
|
|
|
|
|
|
|
// clearing all state bits not being handled from the skin
|
2021-09-14 13:05:56 +02:00
|
|
|
aspect.clearStates( ~skin->stateMask() );
|
2020-08-09 11:50:34 +02:00
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect resolvedAspect;
|
2017-08-22 20:50:55 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
const auto& localTable = m_data->hintTable;
|
|
|
|
if ( localTable.hasHints() )
|
|
|
|
{
|
2020-12-15 07:21:12 +01:00
|
|
|
auto a = aspect;
|
2017-10-17 17:34:00 +02:00
|
|
|
|
|
|
|
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 )
|
|
|
|
{
|
|
|
|
status->source = QskSkinHintStatus::Skinnable;
|
|
|
|
status->aspect = resolvedAspect;
|
|
|
|
}
|
|
|
|
return *value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// next we try the hints from the skin
|
|
|
|
|
2020-03-19 14:10:50 +01:00
|
|
|
const auto& skinTable = skin->hintTable();
|
2017-10-17 17:34:00 +02:00
|
|
|
if ( skinTable.hasHints() )
|
|
|
|
{
|
2020-12-15 07:21:12 +01:00
|
|
|
auto a = aspect;
|
2017-10-17 17:34:00 +02:00
|
|
|
|
|
|
|
const QVariant* value = skinTable.resolvedHint( a, &resolvedAspect );
|
|
|
|
if ( value )
|
|
|
|
{
|
|
|
|
if ( status )
|
|
|
|
{
|
|
|
|
status->source = QskSkinHintStatus::Skin;
|
|
|
|
status->aspect = resolvedAspect;
|
2018-03-22 11:22:13 +01:00
|
|
|
}
|
2017-10-17 17:34:00 +02:00
|
|
|
|
|
|
|
return *value;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( aspect.subControl() != QskAspect::Control )
|
|
|
|
{
|
2019-12-14 13:34:30 +01:00
|
|
|
// trying to resolve something from the skin default settings
|
2017-10-17 17:34:00 +02:00
|
|
|
|
|
|
|
aspect.setSubControl( QskAspect::Control );
|
|
|
|
aspect.clearStates();
|
|
|
|
|
|
|
|
value = skinTable.resolvedHint( aspect, &resolvedAspect );
|
|
|
|
if ( value )
|
|
|
|
{
|
|
|
|
if ( status )
|
|
|
|
{
|
|
|
|
status->source = QskSkinHintStatus::Skin;
|
|
|
|
status->aspect = resolvedAspect;
|
|
|
|
}
|
|
|
|
|
|
|
|
return *value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( status )
|
|
|
|
{
|
|
|
|
status->source = QskSkinHintStatus::NoSource;
|
2020-12-21 16:06:58 +01:00
|
|
|
status->aspect = QskAspect();
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static QVariant hintInvalid;
|
|
|
|
return hintInvalid;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2021-08-30 15:30:41 +02:00
|
|
|
bool QskSkinnable::hasSkinState( QskAspect::State state ) const
|
|
|
|
{
|
2021-09-14 13:05:56 +02:00
|
|
|
return ( m_data->skinStates & state ) == state;
|
2021-08-30 15:30:41 +02:00
|
|
|
}
|
|
|
|
|
2021-09-14 13:05:56 +02:00
|
|
|
QskAspect::States QskSkinnable::skinStates() const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2021-09-14 13:05:56 +02:00
|
|
|
return m_data->skinStates;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2021-09-14 13:05:56 +02:00
|
|
|
const char* QskSkinnable::skinStatesAsPrintable() const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2021-09-14 13:05:56 +02:00
|
|
|
return skinStatesAsPrintable( skinStates() );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2021-09-14 13:05:56 +02:00
|
|
|
const char* QskSkinnable::skinStatesAsPrintable( QskAspect::States states ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
QString tmp;
|
|
|
|
|
|
|
|
QDebug debug( &tmp );
|
2021-09-14 13:05:56 +02:00
|
|
|
qskDebugStates( debug, metaObject(), states );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
// we should find a better way
|
2018-08-03 08:15:28 +02:00
|
|
|
static QByteArray bytes[ 10 ];
|
2017-07-21 18:21:34 +02:00
|
|
|
static int counter = 0;
|
|
|
|
|
|
|
|
counter = ( counter + 1 ) % 10;
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
bytes[ counter ] = tmp.toUtf8();
|
|
|
|
return bytes[ counter ].constData();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-12-17 16:44:54 +01:00
|
|
|
static inline QskMargins qskEffectivePadding( const QskSkinnable* skinnable,
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect aspect, const QSizeF& size, bool inner )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-15 07:21:12 +01:00
|
|
|
const auto shape = skinnable->boxShapeHint( aspect ).toAbsolute( size );
|
|
|
|
const auto borderMetrics = skinnable->boxBorderMetricsHint( aspect );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-12-15 07:21:12 +01:00
|
|
|
const qreal left = qMax( shape.radius( Qt::TopLeftCorner ).width(),
|
|
|
|
shape.radius( Qt::BottomLeftCorner ).width() );
|
2017-10-20 13:09:30 +02:00
|
|
|
|
2020-12-15 07:21:12 +01:00
|
|
|
const qreal top = qMax( shape.radius( Qt::TopLeftCorner ).height(),
|
|
|
|
shape.radius( Qt::TopRightCorner ).height() );
|
2017-10-20 13:09:30 +02:00
|
|
|
|
2020-12-15 07:21:12 +01:00
|
|
|
const qreal right = qMax( shape.radius( Qt::TopRightCorner ).width(),
|
|
|
|
shape.radius( Qt::BottomRightCorner ).width() );
|
2017-10-20 13:09:30 +02:00
|
|
|
|
|
|
|
const qreal bottom = qMax( shape.radius( Qt::BottomLeftCorner ).height(),
|
|
|
|
shape.radius( Qt::BottomRightCorner ).height() );
|
|
|
|
|
2020-12-17 16:44:54 +01:00
|
|
|
QskMargins padding( left, top, right, bottom );
|
2017-10-20 13:09:30 +02:00
|
|
|
|
|
|
|
// half of the border goes to the inner side
|
|
|
|
const auto borderMargins = borderMetrics.toAbsolute( size ).widths() * 0.5;
|
|
|
|
|
|
|
|
if ( inner )
|
|
|
|
{
|
|
|
|
padding -= borderMargins;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// not correct, but to get things started. TODO ...
|
|
|
|
padding += borderMargins;
|
|
|
|
}
|
|
|
|
|
|
|
|
// sin 45° ceiled : 0.70710678;
|
|
|
|
padding *= 1.0 - 0.70710678;
|
|
|
|
|
2020-12-29 12:57:03 +01:00
|
|
|
return padding.expandedTo( skinnable->paddingHint( aspect ) );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-04-18 19:41:46 +02:00
|
|
|
QMarginsF QskSkinnable::innerPadding(
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect aspect, const QSizeF& outerBoxSize ) const
|
2018-04-18 19:41:46 +02:00
|
|
|
{
|
|
|
|
return qskEffectivePadding( this, aspect, outerBoxSize, true );
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
QSizeF QskSkinnable::innerBoxSize(
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect aspect, const QSizeF& outerBoxSize ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-17 16:44:54 +01:00
|
|
|
const auto pd = qskEffectivePadding( this, aspect, outerBoxSize, true );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-12-17 16:44:54 +01:00
|
|
|
return QSizeF( outerBoxSize.width() - pd.width(),
|
|
|
|
outerBoxSize.height() - pd.height() );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QRectF QskSkinnable::innerBox(
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect aspect, const QRectF& outerBox ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-17 16:44:54 +01:00
|
|
|
const auto pd = qskEffectivePadding( this, aspect, outerBox.size(), true );
|
|
|
|
return outerBox.marginsRemoved( pd );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QSizeF QskSkinnable::outerBoxSize(
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect aspect, const QSizeF& innerBoxSize ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-17 16:44:54 +01:00
|
|
|
const auto pd = qskEffectivePadding( this, aspect, innerBoxSize, false );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-12-17 16:44:54 +01:00
|
|
|
// since Qt 5.14 we would have QSizeF::grownBy !
|
|
|
|
return QSizeF( innerBoxSize.width() + pd.width(),
|
|
|
|
innerBoxSize.height() + pd.height() );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QRectF QskSkinnable::outerBox(
|
2020-12-21 16:06:58 +01:00
|
|
|
QskAspect aspect, const QRectF& innerBox ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-08-09 10:45:48 +02:00
|
|
|
const auto m = qskEffectivePadding( this, aspect, innerBox.size(), false );
|
2017-07-21 18:21:34 +02:00
|
|
|
return innerBox.marginsAdded( m );
|
|
|
|
}
|
|
|
|
|
2020-12-29 12:57:03 +01:00
|
|
|
QRectF QskSkinnable::subControlRect(
|
|
|
|
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
|
|
|
{
|
|
|
|
return effectiveSkinlet()->subControlRect( this, contentsRect, subControl );
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF QskSkinnable::subControlContentsRect(
|
|
|
|
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
|
|
|
{
|
|
|
|
return innerBox( subControl, subControlRect( contentsRect, subControl ) );
|
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
bool QskSkinnable::isTransitionAccepted( QskAspect aspect ) const
|
2018-10-10 08:55:03 +02:00
|
|
|
{
|
|
|
|
Q_UNUSED( aspect )
|
|
|
|
|
|
|
|
/*
|
|
|
|
Usually we only need smooth transitions, when state changes
|
|
|
|
happen while the skinnable is visible. There are few exceptions
|
|
|
|
like QskPopup::Closed, that is used to slide/fade in.
|
|
|
|
*/
|
|
|
|
if ( auto control = owningControl() )
|
|
|
|
return control->isInitiallyPainted();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
void QskSkinnable::startTransition( QskAspect aspect,
|
2017-07-21 18:21:34 +02:00
|
|
|
QskAnimationHint animationHint, QVariant from, QVariant to )
|
2020-12-21 15:27:05 +01:00
|
|
|
{
|
|
|
|
aspect.setSubControl( effectiveSubcontrol( aspect.subControl() ) );
|
|
|
|
startHintTransition( aspect, animationHint, from, to );
|
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
void QskSkinnable::startHintTransition( QskAspect aspect,
|
2020-12-21 15:27:05 +01:00
|
|
|
QskAnimationHint animationHint, QVariant from, QVariant to )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
if ( animationHint.duration <= 0 || ( from == to ) )
|
|
|
|
return;
|
|
|
|
|
2020-08-09 10:45:48 +02:00
|
|
|
auto control = this->owningControl();
|
2018-10-10 08:55:03 +02:00
|
|
|
if ( control->window() == nullptr || !isTransitionAccepted( aspect ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
return;
|
|
|
|
|
2018-12-20 16:40:06 +01:00
|
|
|
/*
|
|
|
|
We might be invalid for one of the values, when an aspect
|
|
|
|
has not been defined for all states ( f.e. metrics are expected
|
|
|
|
to fallback to 0.0 ). In this case we create a default one.
|
|
|
|
*/
|
2017-09-05 12:48:58 +02:00
|
|
|
|
|
|
|
if ( !from.isValid() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-10-23 14:00:27 +02:00
|
|
|
from = qskTypedNullValue( to );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
2017-09-05 12:48:58 +02:00
|
|
|
else if ( !to.isValid() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-10-23 14:00:27 +02:00
|
|
|
to = qskTypedNullValue( from );
|
2017-09-05 12:48:58 +02:00
|
|
|
}
|
2018-12-20 16:40:06 +01:00
|
|
|
else if ( from.userType() != to.userType() )
|
2017-09-05 12:48:58 +02:00
|
|
|
{
|
|
|
|
return;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( aspect.flagPrimitive() == QskAspect::GraphicRole )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
const auto skin = effectiveSkin();
|
|
|
|
|
|
|
|
from.setValue( skin->graphicFilter( from.toInt() ) );
|
|
|
|
to.setValue( skin->graphicFilter( to.toInt() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
aspect.clearStates();
|
|
|
|
aspect.setAnimator( false );
|
2017-10-17 17:34:00 +02:00
|
|
|
aspect.setPlacement( effectivePlacement() );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
#if DEBUG_ANIMATOR
|
2018-02-06 14:58:24 +01:00
|
|
|
qDebug() << aspect << animationHint.duration;
|
2017-10-17 17:34:00 +02:00
|
|
|
#endif
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
auto animator = m_data->animators.animator( aspect );
|
|
|
|
if ( animator && animator->isRunning() )
|
|
|
|
from = animator->currentValue();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
m_data->animators.start( control, aspect, animationHint, from, to );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-12-22 16:11:24 +01:00
|
|
|
void QskSkinnable::setSkinStateFlag( QskAspect::State stateFlag, bool on )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
const auto newState = on
|
2021-09-14 13:05:56 +02:00
|
|
|
? ( m_data->skinStates | stateFlag )
|
|
|
|
: ( m_data->skinStates & ~stateFlag );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2021-09-17 16:32:01 +02:00
|
|
|
setSkinStates( newState );
|
2018-12-22 16:11:24 +01:00
|
|
|
}
|
|
|
|
|
2021-09-14 13:05:56 +02:00
|
|
|
void QskSkinnable::replaceSkinStates( QskAspect::States newStates )
|
2021-04-21 09:29:52 +02:00
|
|
|
{
|
2021-09-14 13:05:56 +02:00
|
|
|
m_data->skinStates = newStates;
|
2021-04-21 09:29:52 +02:00
|
|
|
}
|
|
|
|
|
2021-09-17 16:32:01 +02:00
|
|
|
void QskSkinnable::addSkinStates( QskAspect::States states )
|
|
|
|
{
|
|
|
|
setSkinStates( m_data->skinStates | states );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskSkinnable::clearSkinStates( QskAspect::States states )
|
|
|
|
{
|
|
|
|
setSkinStates( m_data->skinStates & ~states );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskSkinnable::setSkinStates( QskAspect::States newStates )
|
2018-12-22 16:11:24 +01:00
|
|
|
{
|
2021-09-14 13:05:56 +02:00
|
|
|
if ( m_data->skinStates == newStates )
|
2017-07-21 18:21:34 +02:00
|
|
|
return;
|
|
|
|
|
2020-03-19 14:10:50 +01:00
|
|
|
auto control = owningControl();
|
2017-09-05 12:48:58 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
#if DEBUG_STATE
|
2018-03-22 11:22:13 +01:00
|
|
|
qDebug() << control->className() << ":"
|
2017-09-05 12:48:58 +02:00
|
|
|
<< skinStateAsPrintable( m_data->skinState ) << "->"
|
|
|
|
<< skinStateAsPrintable( newState );
|
|
|
|
#endif
|
|
|
|
|
2020-03-19 14:10:50 +01:00
|
|
|
const auto skin = effectiveSkin();
|
|
|
|
|
|
|
|
if ( skin )
|
|
|
|
{
|
|
|
|
const auto mask = skin->stateMask();
|
2021-09-14 13:05:56 +02:00
|
|
|
if ( ( newStates & mask ) == ( m_data->skinStates & mask ) )
|
2020-03-19 14:10:50 +01:00
|
|
|
{
|
|
|
|
// the modified bits are not handled by the skin
|
|
|
|
|
2021-09-14 13:05:56 +02:00
|
|
|
m_data->skinStates = newStates;
|
2020-03-19 14:10:50 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-17 16:32:01 +02:00
|
|
|
if ( control->window() && isTransitionAccepted( QskAspect() ) )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-10-17 17:34:00 +02:00
|
|
|
const auto placement = effectivePlacement();
|
2021-04-27 10:11:10 +02:00
|
|
|
const auto primitiveCount = QskAspect::primitiveCount();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-30 12:06:19 +01:00
|
|
|
const auto subControls = control->subControls();
|
|
|
|
for ( const auto subControl : subControls )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
2020-12-13 14:23:17 +01:00
|
|
|
auto aspect = subControl | placement;
|
2017-08-22 20:50:55 +02:00
|
|
|
|
2020-03-19 14:10:50 +01:00
|
|
|
const auto& skinTable = skin->hintTable();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2020-12-18 13:09:22 +01:00
|
|
|
for ( uint i = 0; i < QskAspect::typeCount; i++ )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2020-12-15 07:21:12 +01:00
|
|
|
const auto type = static_cast< QskAspect::Type >( i );
|
2017-10-17 17:34:00 +02:00
|
|
|
|
2021-09-14 13:05:56 +02:00
|
|
|
const auto hint = effectiveAnimation( type, subControl, newStates );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
if ( hint.duration > 0 )
|
2017-08-22 20:50:55 +02:00
|
|
|
{
|
2017-10-17 17:34:00 +02:00
|
|
|
/*
|
|
|
|
Starting an animator for all primitives,
|
|
|
|
that differ between the states
|
|
|
|
*/
|
2020-12-18 13:09:22 +01:00
|
|
|
|
2021-04-27 10:11:10 +02:00
|
|
|
for ( uint i = 0; i < primitiveCount; i++ )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
2021-04-27 10:11:10 +02:00
|
|
|
const auto primitive = static_cast< QskAspect::Primitive >( i );
|
2017-10-17 17:34:00 +02:00
|
|
|
aspect.setPrimitive( type, primitive );
|
|
|
|
|
2021-09-14 13:05:56 +02:00
|
|
|
auto a1 = aspect | m_data->skinStates;
|
|
|
|
auto a2 = aspect | newStates;
|
2017-10-17 17:34:00 +02:00
|
|
|
|
|
|
|
bool doTransition = true;
|
|
|
|
|
|
|
|
if ( !m_data->hintTable.hasStates() )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
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.
|
2018-03-22 11:22:13 +01:00
|
|
|
|
2017-10-17 17:34:00 +02:00
|
|
|
*/
|
2020-12-26 13:00:09 +01:00
|
|
|
doTransition = !skinTable.isResolutionMatching( a1, a2 );
|
2017-10-17 17:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( doTransition )
|
|
|
|
{
|
2020-12-21 16:06:58 +01:00
|
|
|
startHintTransition( aspect, hint,
|
2017-10-17 17:34:00 +02:00
|
|
|
storedHint( a1 ), storedHint( a2 ) );
|
|
|
|
}
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-14 13:05:56 +02:00
|
|
|
m_data->skinStates = newStates;
|
2018-07-02 08:08:08 +02:00
|
|
|
|
|
|
|
if ( control->flags() & QQuickItem::ItemHasContents )
|
|
|
|
control->update();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QskSkin* QskSkinnable::effectiveSkin() const
|
|
|
|
{
|
2020-03-19 14:10:50 +01:00
|
|
|
QskSkin* skin = nullptr;
|
|
|
|
|
|
|
|
if ( m_data->skinlet )
|
|
|
|
skin = m_data->skinlet->skin();
|
|
|
|
|
2021-09-09 07:53:35 +02:00
|
|
|
if ( skin == nullptr )
|
|
|
|
{
|
|
|
|
if ( const auto control = owningControl() )
|
|
|
|
{
|
|
|
|
if ( auto window = qobject_cast< const QskWindow* >( control->window() ) )
|
|
|
|
{
|
|
|
|
skin = window->skin();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
return skin ? skin : qskSetup->skin();
|
|
|
|
}
|
|
|
|
|
2020-12-20 16:10:24 +01:00
|
|
|
QskAspect::Placement QskSkinnable::effectivePlacement() const
|
|
|
|
{
|
|
|
|
return QskAspect::NoPlacement;
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
void QskSkinnable::updateNode( QSGNode* parentNode )
|
|
|
|
{
|
|
|
|
effectiveSkinlet()->updateNode( this, parentNode );
|
|
|
|
}
|
|
|
|
|
|
|
|
QskAspect::Subcontrol QskSkinnable::effectiveSubcontrol(
|
|
|
|
QskAspect::Subcontrol subControl ) const
|
2021-08-04 15:06:04 +02:00
|
|
|
{
|
|
|
|
if ( const auto proxies = m_data->subcontrolProxies )
|
|
|
|
{
|
|
|
|
auto it = proxies->find( subControl );
|
|
|
|
if ( it != proxies->end() )
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
return substitutedSubcontrol( subControl );
|
|
|
|
}
|
|
|
|
|
|
|
|
QskAspect::Subcontrol QskSkinnable::substitutedSubcontrol(
|
|
|
|
QskAspect::Subcontrol subControl ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
// derived classes might want to redirect a sub-control
|
|
|
|
return subControl;
|
|
|
|
}
|
|
|
|
|
|
|
|
QskControl* QskSkinnable::controlCast()
|
|
|
|
{
|
|
|
|
return qskIsControl( this )
|
|
|
|
? static_cast< QskControl* >( this ) : nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const QskControl* QskSkinnable::controlCast() const
|
|
|
|
{
|
|
|
|
return qskIsControl( this )
|
|
|
|
? static_cast< const QskControl* >( this ) : nullptr;
|
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
void QskSkinnable::debug( QDebug debug, QskAspect aspect ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
qskDebugAspect( debug, metaObject(), aspect );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskSkinnable::debug( QDebug debug, QskAspect::State state ) const
|
|
|
|
{
|
2021-09-14 13:05:56 +02:00
|
|
|
qskDebugStates( debug, metaObject(), state );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2020-12-21 16:06:58 +01:00
|
|
|
void QskSkinnable::debug( QskAspect aspect ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
qskDebugAspect( qDebug(), metaObject(), aspect );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskSkinnable::debug( QskAspect::State state ) const
|
|
|
|
{
|
2021-09-14 13:05:56 +02:00
|
|
|
qskDebugStates( qDebug(), metaObject(), state );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
2020-09-28 09:04:25 +02:00
|
|
|
|
|
|
|
#ifndef QT_NO_DEBUG_STREAM
|
|
|
|
|
|
|
|
#include <qdebug.h>
|
|
|
|
|
|
|
|
QDebug operator<<( QDebug debug, const QskSkinHintStatus& status )
|
|
|
|
{
|
|
|
|
QDebugStateSaver saver( debug );
|
|
|
|
debug.nospace();
|
|
|
|
|
|
|
|
switch( status.source )
|
|
|
|
{
|
|
|
|
case QskSkinHintStatus::Skinnable:
|
|
|
|
debug << "Skinnable";
|
|
|
|
break;
|
|
|
|
case QskSkinHintStatus::Skin:
|
|
|
|
debug << "Skin";
|
|
|
|
break;
|
|
|
|
case QskSkinHintStatus::Animator:
|
|
|
|
debug << "Animator";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
debug << "None";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
debug << ": " << status.aspect;
|
|
|
|
|
|
|
|
return debug;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|