smooth transition of font sizes added

This commit is contained in:
Uwe Rathmann 2024-02-23 13:46:23 +01:00
parent 87c16d453b
commit d0a888ab74
4 changed files with 136 additions and 18 deletions

View File

@ -124,6 +124,22 @@ static inline QskSkinlet* qskNewSkinlet( const QMetaObject* metaObject, QskSkin*
return skinlet;
}
// also used in QskSkinTransition.cpp TODO ...
QFont qskResolvedFont( const QHash< QskFontRole, QFont >& fontTable,
const QskFontRole& fontRole )
{
auto it = fontTable.constFind( fontRole );
if ( it != fontTable.constEnd() )
return it.value();
it = fontTable.constFind( QskFontRole() );
if ( it != fontTable.constEnd() )
return it.value();
return QGuiApplication::font();
}
namespace
{
class SkinletData
@ -374,17 +390,7 @@ void QskSkin::resetFont( const QskFontRole& fontRole )
QFont QskSkin::font( const QskFontRole& fontRole ) const
{
const auto& table = m_data->fonts;
auto it = table.constFind( fontRole );
if ( it != table.constEnd() )
return it.value();
it = table.constFind( QskFontRole() );
if ( it != m_data->fonts.constEnd() )
return it.value();
return QGuiApplication::font();
return qskResolvedFont( m_data->fonts, fontRole );
}
void QskSkin::setGraphicFilter( int graphicRole, const QskColorFilter& colorFilter )

View File

@ -11,6 +11,8 @@
#include "QskHintAnimator.h"
#include "QskSkin.h"
#include "QskSkinHintTable.h"
#include "QskFontRole.h"
#include "QskAspect.h"
#include <qglobalstatic.h>
#include <qguiapplication.h>
@ -86,12 +88,10 @@ static void qskAddCandidates( const QskSkinTransition::Type mask,
{
isCandidate = mask & QskSkinTransition::Color;
}
#if 0
else if ( aspect.primitive() == QskAspect::FontRole )
{
isCandidate = mask & QskSkinTransition::Metric;
}
#endif
break;
}
case QskAspect::Color:
@ -161,10 +161,14 @@ namespace
QVariant animatedHint( QskAspect ) const;
QVariant animatedGraphicFilter( int graphicRole ) const;
QVariant animatedFontSize( const QskFontRole& ) const;
void addGraphicFilterAnimators( const QskAnimationHint&,
const QHash< int, QskColorFilter >&, const QHash< int, QskColorFilter >& );
void addFontSizeAnimators( const QskAnimationHint&,
const QHash< QskFontRole, QFont >&, const QHash< QskFontRole, QFont >& );
void addItemAspects( QQuickItem*,
const QskAnimationHint&, const QSet< QskAspect >&,
const QskSkinHintTable&, const QskSkinHintTable& );
@ -186,8 +190,11 @@ namespace
void storeUpdateInfo( const QskControl*, QskAspect );
QQuickWindow* m_window;
QHash< QskAspect, HintAnimator > m_animatorMap;
QHash< int, QskVariantAnimator > m_graphicFilterAnimatorMap;
QHash< QskFontRole, QskVariantAnimator > m_fontSizeAnimatorMap;
std::vector< UpdateInfo > m_updateInfos; // vector: for fast iteration
};
@ -243,6 +250,9 @@ void WindowAnimator::start()
for ( auto& it : m_graphicFilterAnimatorMap )
it.start();
for ( auto& it : m_fontSizeAnimatorMap )
it.start();
}
bool WindowAnimator::isRunning() const
@ -261,6 +271,13 @@ bool WindowAnimator::isRunning() const
return true;
}
if ( !m_fontSizeAnimatorMap.empty() )
{
const auto& animator = m_fontSizeAnimatorMap.constBegin().value();
if ( animator.isRunning() )
return true;
}
return false;
}
@ -290,6 +307,19 @@ inline QVariant WindowAnimator::animatedGraphicFilter( int graphicRole ) const
return QVariant();
}
inline QVariant WindowAnimator::animatedFontSize( const QskFontRole& fontRole ) const
{
auto it = m_fontSizeAnimatorMap.constFind( fontRole );
if ( it != m_fontSizeAnimatorMap.constEnd() )
{
const auto& animator = it.value();
if ( animator.isRunning() )
return animator.currentValue();
}
return QVariant();
}
void WindowAnimator::addGraphicFilterAnimators(
const QskAnimationHint& animatorHint,
const QHash< int, QskColorFilter >& filters1,
@ -320,6 +350,42 @@ void WindowAnimator::addGraphicFilterAnimators(
}
}
// from QskSkin.cpp
extern QFont qskResolvedFont(
const QHash< QskFontRole, QFont >&, const QskFontRole& );
void WindowAnimator::addFontSizeAnimators(
const QskAnimationHint& animatorHint,
const QHash< QskFontRole, QFont >& fonts1,
const QHash< QskFontRole, QFont >& fonts2 )
{
for ( int i = 0; i <= QskFontRole::Display; i++ )
{
for ( int j = 0; j <= QskFontRole::VeryHigh; j++ )
{
const QskFontRole fontRole(
static_cast< QskFontRole::Category >( i ),
static_cast< QskFontRole::Emphasis >( j )
);
const auto size1 = qskResolvedFont( fonts1, fontRole ).pixelSize();
const auto size2 = qskResolvedFont( fonts2, fontRole ).pixelSize();
if ( ( size1 > 0 ) && ( size2 > 0 ) && ( size1 != size2 ) )
{
QskVariantAnimator animator;
animator.setWindow( m_window );
animator.setDuration( animatorHint.duration );
animator.setEasingCurve( animatorHint.type );
animator.setStartValue( QVariant::fromValue( size1 ) );
animator.setEndValue( QVariant::fromValue( size2 ) );
m_fontSizeAnimatorMap.insert( fontRole, animator );
}
}
}
}
void WindowAnimator::addItemAspects( QQuickItem* item,
const QskAnimationHint& animatorHint, const QSet< QskAspect >& candidates,
const QskSkinHintTable& table1, const QskSkinHintTable& table2 )
@ -602,6 +668,7 @@ class QskSkinTransition::PrivateData
{
QskSkinHintTable hintTable;
QHash< int, QskColorFilter > graphicFilters;
QHash< QskFontRole, QFont > fontTable;
} tables[ 2 ];
Type mask = QskSkinTransition::AllTypes;
@ -632,6 +699,7 @@ void QskSkinTransition::setSourceSkin( const QskSkin* skin )
tables.hintTable = skin->hintTable();
tables.graphicFilters = skin->graphicFilters();
tables.fontTable = skin->fontTable();
}
void QskSkinTransition::setTargetSkin( const QskSkin* skin )
@ -640,6 +708,7 @@ void QskSkinTransition::setTargetSkin( const QskSkin* skin )
tables.hintTable = skin->hintTable();
tables.graphicFilters = skin->graphicFilters();
tables.fontTable = skin->fontTable();
}
void QskSkinTransition::run( const QskAnimationHint& animationHint )
@ -652,6 +721,9 @@ void QskSkinTransition::run( const QskAnimationHint& animationHint )
const auto& graphicFilters1 = m_data->tables[ 0 ].graphicFilters;
const auto& graphicFilters2 = m_data->tables[ 1 ].graphicFilters;
const auto& fontTable1 = m_data->tables[ 0 ].fontTable;
const auto& fontTable2 = m_data->tables[ 1 ].fontTable;
QSet< QskAspect > candidates;
if ( ( animationHint.duration > 0 ) && ( m_data->mask != 0 ) )
@ -663,6 +735,7 @@ void QskSkinTransition::run( const QskAnimationHint& animationHint )
if ( !candidates.isEmpty() )
{
bool doGraphicFilter = m_data->mask & QskSkinTransition::Color;
bool doFont = m_data->mask & QskSkinTransition::Metric;
const auto windows = qGuiApp->topLevelWindows();
@ -686,6 +759,12 @@ void QskSkinTransition::run( const QskAnimationHint& animationHint )
doGraphicFilter = false;
}
if ( doFont )
{
animator->addFontSizeAnimators( animationHint,
fontTable1, fontTable2 );
}
/*
finally we schedule the animators the hard way by running
over the the item trees.
@ -734,4 +813,16 @@ QVariant QskSkinTransition::animatedGraphicFilter(
return QVariant();
}
QVariant QskSkinTransition::animatedFontSize(
const QQuickWindow* window, const QskFontRole& fontRole )
{
if ( qskApplicationAnimator.exists() )
{
if ( const auto animator = qskApplicationAnimator->windowAnimator( window ) )
return animator->animatedFontSize( fontRole );
}
return QVariant();
}
#include "QskSkinTransition.moc"

View File

@ -6,14 +6,17 @@
#ifndef QSK_SKIN_TRANSITION_H
#define QSK_SKIN_TRANSITION_H
#include "QskAspect.h"
#include "QskGlobal.h"
#include <memory>
class QskAnimationHint;
class QskFontRole;
class QskAspect;
class QskSkin;
class QQuickWindow;
class QVariant;
template< typename Key, typename T > class QHash;
class QSK_EXPORT QskSkinTransition
@ -39,8 +42,10 @@ class QSK_EXPORT QskSkinTransition
void run( const QskAnimationHint& );
static bool isRunning();
static QVariant animatedHint( const QQuickWindow*, QskAspect );
static QVariant animatedGraphicFilter( const QQuickWindow*, int graphicRole );
static QVariant animatedFontSize( const QQuickWindow*, const QskFontRole& );
private:
Q_DISABLE_COPY( QskSkinTransition )

View File

@ -130,7 +130,7 @@ static inline constexpr QskAspect qskAnimatorAspect( const QskAspect aspect )
the effective aspect in animatedHint.
*/
return aspect.type() | aspect.subControl() | aspect.primitive();
return aspect.type() | aspect.subControl() | aspect.primitive();
}
static inline void qskTriggerUpdates( QskAspect aspect, QQuickItem* item )
@ -724,7 +724,7 @@ QskFontRole QskSkinnable::fontRoleHint(
aspect | QskAspect::FontRole, status ).value< QskFontRole >();
}
QFont QskSkinnable::effectiveFont( const QskAspect aspect ) const
QFont QskSkinnable::effectiveFont( QskAspect aspect ) const
{
const auto hint = effectiveSkinHint( aspect | QskAspect::FontRole );
if ( hint.canConvert< QFont >() )
@ -736,8 +736,24 @@ QFont QskSkinnable::effectiveFont( const QskAspect aspect ) const
*/
return hint.value< QFont >();
}
return effectiveSkin()->font( hint.value< QskFontRole >() );
const auto fontRole = hint.value< QskFontRole >();
auto font = effectiveSkin()->font( fontRole );
if ( auto item = owningItem() )
{
const auto v = QskSkinTransition::animatedFontSize(
item->window(), fontRole );
if ( v.canConvert< int >() )
{
font.setPixelSize( v.value< int >() );
item->update(); // design flaw: see effectiveGraphicFilter
}
}
return font;
}
qreal QskSkinnable::effectiveFontHeight( const QskAspect aspect ) const