QskFocusIndicator using enabled/disabled isntead of Exposed/Concealed

This commit is contained in:
Uwe Rathmann 2023-12-02 12:05:44 +01:00
parent 1dee82c29e
commit 6fa8cd9dc3
4 changed files with 83 additions and 112 deletions

View File

@ -2,51 +2,24 @@
#include <QskEvent.h> #include <QskEvent.h>
#include <QskAnimationHint.h> #include <QskAnimationHint.h>
#include <QskBoxBorderMetrics.h>
#include <QskBoxShapeMetrics.h>
#include <QskBoxBorderColors.h>
#include <QskRgbValue.h>
#include <qquickwindow.h> #include <qquickwindow.h>
#include <qbasictimer.h> #include <qbasictimer.h>
static inline bool qskIsEnablingKey( const QKeyEvent* event )
QSK_STATE( FocusIndicator, Concealed, QskAspect::FirstUserState )
static inline bool qskIsExposingKeyPress( const QKeyEvent* event )
{ {
// what keys do we want have here ??? // what keys do we want have here ???
return qskIsButtonPressKey( event ) || qskFocusChainIncrement( event ); return qskIsButtonPressKey( event ) || qskFocusChainIncrement( event );
} }
static void qskMaybeExpose( FocusIndicator* indicator, bool on )
{
Q_UNUSED( indicator );
Q_UNUSED( on );
#if 0
if ( on )
{
if ( auto w = indicator->window() )
{
if ( w->isExposed() && w->isActive() )
indicator->setExposed( true );
}
}
else
{
indicator->setExposed( false );
}
#endif
}
class FocusIndicator::PrivateData class FocusIndicator::PrivateData
{ {
public: public:
inline bool isAutoConcealing() const { return timeout > 0; } inline bool isAutoDisabling() const { return duration > 0; }
inline bool isAutoEnabling() const { return false; }
int timeout = 0; int duration = 0;
QBasicTimer concealTimer; QBasicTimer timer;
bool blockAutoRepeatKeyEvents = false; bool blockAutoRepeatKeyEvents = false;
}; };
@ -55,85 +28,94 @@ FocusIndicator::FocusIndicator( QQuickItem* parent )
: Inherited( parent ) : Inherited( parent )
, m_data( new PrivateData() ) , m_data( new PrivateData() )
{ {
#if 1 setDuration( 4500 );
auto colors = boxBorderColorsHint( Panel );
setBoxBorderColorsHint( Panel | Concealed, QskRgb::Transparent );
setAnimationHint( Panel | QskAspect::Color, 200 );
setAnimationHint( Panel | QskAspect::Color | Concealed, 500 );
#endif
setExposedTimeout( 4500 );
} }
FocusIndicator::~FocusIndicator() FocusIndicator::~FocusIndicator()
{ {
} }
void FocusIndicator::setExposedTimeout( int ms ) void FocusIndicator::setDuration( int ms )
{ {
ms = std::max( ms, 0 ); ms = std::max( ms, 0 );
if ( ms == m_data->timeout ) if ( ms == m_data->duration )
return; return;
m_data->timeout = ms; m_data->duration = ms;
if ( m_data->isAutoConcealing() ) if ( m_data->isAutoDisabling() )
{ {
if ( auto w = window() ) if ( auto w = window() )
w->installEventFilter( this ); w->installEventFilter( this );
if ( isExposed() ) if ( isEnabled() )
{ {
if ( isInitiallyPainted() ) if ( isInitiallyPainted() )
m_data->concealTimer.start( m_data->timeout, this ); m_data->timer.start( m_data->duration, this );
else else
setExposed( false ); setEnabled( false );
} }
connect( this, &QQuickItem::enabledChanged,
this, &FocusIndicator::resetTimer );
} }
else else
{ {
if ( auto w = window() ) if ( auto w = window() )
w->removeEventFilter( this ); w->removeEventFilter( this );
setExposed( true ); setEnabled( true );
disconnect( this, &QQuickItem::enabledChanged,
this, &FocusIndicator::resetTimer );
} }
Q_EMIT exposedTimeoutChanged( ms ); Q_EMIT durationChanged( ms );
} }
int FocusIndicator::exposedTimeout() const int FocusIndicator::duration() const
{ {
return m_data->timeout; return m_data->duration;
} }
void FocusIndicator::setExposed( bool on ) void FocusIndicator::maybeEnable( bool on )
{ {
if ( on == isExposed() ) if ( !m_data->isAutoEnabling() )
return; return;
setSkinStateFlag( Concealed, !on );
if ( m_data->isAutoConcealing() )
{
if ( on ) if ( on )
{ {
const auto hint = animationHint( Panel | QskAspect::Color ); if ( auto w = window() )
m_data->concealTimer.start( m_data->timeout + hint.duration, this ); {
if ( w->isExposed() && w->isActive() )
setEnabled( true );
}
} }
else else
{ {
m_data->concealTimer.stop(); setEnabled( false );
} }
} }
Q_EMIT exposedChanged( on ); void FocusIndicator::resetTimer()
{
if ( m_data->isAutoDisabling() )
{
if ( isEnabled() )
{
const auto hint = animationHint( Panel | QskAspect::Color );
m_data->timer.start( m_data->duration + hint.duration, this );
}
else
{
m_data->timer.stop();
}
}
} }
bool FocusIndicator::eventFilter( QObject* object, QEvent* event ) bool FocusIndicator::eventFilter( QObject* object, QEvent* event )
{ {
if( ( object != window() ) || !m_data->isAutoConcealing() ) if( ( object != window() ) || !m_data->isAutoDisabling() )
return Inherited::eventFilter( object, event ); return Inherited::eventFilter( object, event );
switch( static_cast< int >( event->type() ) ) switch( static_cast< int >( event->type() ) )
@ -141,13 +123,15 @@ bool FocusIndicator::eventFilter( QObject* object, QEvent* event )
case QEvent::KeyPress: case QEvent::KeyPress:
case QEvent::KeyRelease: case QEvent::KeyRelease:
case QEvent::ShortcutOverride: case QEvent::ShortcutOverride:
if ( m_data->concealTimer.isActive() ) {
if ( m_data->timer.isActive() )
{ {
// renew the exposed period // renew the exposed period
m_data->concealTimer.start( m_data->timeout, this ); m_data->timer.start( m_data->duration, this );
} }
break; break;
} }
}
switch( static_cast< int >( event->type() ) ) switch( static_cast< int >( event->type() ) )
{ {
@ -164,9 +148,9 @@ bool FocusIndicator::eventFilter( QObject* object, QEvent* event )
return true; return true;
} }
if ( !isExposed() && qskIsExposingKeyPress( keyEvent ) ) if ( !isEnabled() && qskIsEnablingKey( keyEvent ) )
{ {
setExposed( true ); setEnabled( true );
m_data->blockAutoRepeatKeyEvents = true; m_data->blockAutoRepeatKeyEvents = true;
return true; return true;
} }
@ -192,7 +176,7 @@ bool FocusIndicator::eventFilter( QObject* object, QEvent* event )
case QEvent::FocusIn: case QEvent::FocusIn:
case QEvent::FocusOut: case QEvent::FocusOut:
{ {
qskMaybeExpose( this, event->type() != QEvent::FocusOut ); maybeEnable( event->type() != QEvent::FocusOut );
break; break;
} }
} }
@ -204,7 +188,7 @@ void FocusIndicator::windowChangeEvent( QskWindowChangeEvent* event )
{ {
Inherited::windowChangeEvent( event ); Inherited::windowChangeEvent( event );
if ( m_data->isAutoConcealing() ) if ( m_data->isAutoDisabling() )
{ {
if ( auto w = event->oldWindow() ) if ( auto w = event->oldWindow() )
w->removeEventFilter( this ); w->removeEventFilter( this );
@ -212,18 +196,18 @@ void FocusIndicator::windowChangeEvent( QskWindowChangeEvent* event )
if( auto w = event->window() ) if( auto w = event->window() )
{ {
w->installEventFilter( this ); w->installEventFilter( this );
qskMaybeExpose( this, true ); maybeEnable( true );
} }
} }
} }
void FocusIndicator::timerEvent( QTimerEvent* event ) void FocusIndicator::timerEvent( QTimerEvent* event )
{ {
if ( m_data->isAutoConcealing() ) if ( m_data->isAutoDisabling() )
{ {
if( event->timerId() == m_data->concealTimer.timerId() ) if( event->timerId() == m_data->timer.timerId() )
{ {
setExposed( false ); setEnabled( false );
return; return;
} }
} }
@ -231,9 +215,4 @@ void FocusIndicator::timerEvent( QTimerEvent* event )
Inherited::timerEvent( event ); Inherited::timerEvent( event );
} }
bool FocusIndicator::isExposed() const
{
return !hasSkinState( Concealed );
}
#include "moc_FocusIndicator.cpp" #include "moc_FocusIndicator.cpp"

View File

@ -2,59 +2,35 @@
#include <QskFocusIndicator.h> #include <QskFocusIndicator.h>
/*
A focus indicator, that becomes temporarily visible when using the keyboard
It is intended to move the code to QskFocusIndicator later.
*/
class FocusIndicator : public QskFocusIndicator class FocusIndicator : public QskFocusIndicator
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY( bool exposed READ isExposed Q_PROPERTY( int duration READ duration
WRITE setExposed NOTIFY exposedChanged ) WRITE setDuration NOTIFY durationChanged )
Q_PROPERTY( int exposedTimeout READ exposedTimeout
WRITE setExposedTimeout NOTIFY exposedTimeoutChanged )
using Inherited = QskFocusIndicator; using Inherited = QskFocusIndicator;
public: public:
QSK_STATES( Concealed )
FocusIndicator( QQuickItem* parent = nullptr ); FocusIndicator( QQuickItem* parent = nullptr );
~FocusIndicator() override; ~FocusIndicator() override;
bool isExposed() const;
bool isConcealed() const;
bool eventFilter( QObject*, QEvent* ) override; bool eventFilter( QObject*, QEvent* ) override;
void setExposedTimeout( int ms ); void setDuration( int ms );
int exposedTimeout() const; int duration() const;
public Q_SLOTS:
void setExposed( bool = true );
void setConcealed( bool = true );
Q_SIGNALS: Q_SIGNALS:
void exposedChanged( bool ); void durationChanged( int );
void exposedTimeoutChanged( int );
protected: protected:
void windowChangeEvent( QskWindowChangeEvent* ) override; void windowChangeEvent( QskWindowChangeEvent* ) override;
void timerEvent( QTimerEvent* ) override; void timerEvent( QTimerEvent* ) override;
private: private:
void resetTimer();
void maybeEnable( bool );
class PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;
}; };
inline void FocusIndicator::setConcealed( bool on )
{
setExposed( !on );
}
inline bool FocusIndicator::isConcealed() const
{
return !isExposed();
}

View File

@ -646,9 +646,18 @@ void Editor::setupFocusIndicatorColors(
QskAspect::Section section, const QskFluent2Theme& theme ) QskAspect::Section section, const QskFluent2Theme& theme )
{ {
using Q = QskFocusIndicator; using Q = QskFocusIndicator;
using A = QskAspect;
const auto& pal = theme.palette; const auto& pal = theme.palette;
setBoxBorderColors( Q::Panel | section, pal.strokeColor.focus.outer ); const auto aspect = Q::Panel | section;
const auto color = pal.strokeColor.focus.outer;
setBoxBorderColors( aspect, color );
setBoxBorderColors( aspect | Q::Disabled, QskRgb::toTransparent( color, 0 ) );
setAnimation( Q::Panel | A::Color, 200 );
setAnimation( Q::Panel | A::Color | Q::Disabled, 500 );
} }
void Editor::setupListViewMetrics() void Editor::setupListViewMetrics()

View File

@ -555,12 +555,19 @@ void Editor::setupProgressRing()
void Editor::setupFocusIndicator() void Editor::setupFocusIndicator()
{ {
using Q = QskFocusIndicator; using Q = QskFocusIndicator;
using A = QskAspect;
setPadding( Q::Panel, 5 ); setPadding( Q::Panel, 5 );
setBoxBorderMetrics( Q::Panel, 2 ); setBoxBorderMetrics( Q::Panel, 2 );
setBoxShape( Q::Panel, 4 ); setBoxShape( Q::Panel, 4 );
setGradient( Q::Panel, Qt::transparent ); setGradient( Q::Panel, Qt::transparent );
setBoxBorderColors( Q::Panel, m_pal.highlighted ); setBoxBorderColors( Q::Panel, m_pal.highlighted );
setBoxBorderColors( Q::Panel | Q::Disabled,
QskRgb::toTransparent( m_pal.highlighted, 0 ) );
setAnimation( Q::Panel | A::Color, 200 );
setAnimation( Q::Panel | A::Color | Q::Disabled, 500 );
} }
void Editor::setupSeparator() void Editor::setupSeparator()