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

View File

@ -2,59 +2,35 @@
#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
{
Q_OBJECT
Q_PROPERTY( bool exposed READ isExposed
WRITE setExposed NOTIFY exposedChanged )
Q_PROPERTY( int exposedTimeout READ exposedTimeout
WRITE setExposedTimeout NOTIFY exposedTimeoutChanged )
Q_PROPERTY( int duration READ duration
WRITE setDuration NOTIFY durationChanged )
using Inherited = QskFocusIndicator;
public:
QSK_STATES( Concealed )
FocusIndicator( QQuickItem* parent = nullptr );
~FocusIndicator() override;
bool isExposed() const;
bool isConcealed() const;
bool eventFilter( QObject*, QEvent* ) override;
void setExposedTimeout( int ms );
int exposedTimeout() const;
public Q_SLOTS:
void setExposed( bool = true );
void setConcealed( bool = true );
void setDuration( int ms );
int duration() const;
Q_SIGNALS:
void exposedChanged( bool );
void exposedTimeoutChanged( int );
void durationChanged( int );
protected:
void windowChangeEvent( QskWindowChangeEvent* ) override;
void timerEvent( QTimerEvent* ) override;
private:
void resetTimer();
void maybeEnable( bool );
class PrivateData;
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 )
{
using Q = QskFocusIndicator;
using A = QskAspect;
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()

View File

@ -555,12 +555,19 @@ void Editor::setupProgressRing()
void Editor::setupFocusIndicator()
{
using Q = QskFocusIndicator;
using A = QskAspect;
setPadding( Q::Panel, 5 );
setBoxBorderMetrics( Q::Panel, 2 );
setBoxShape( Q::Panel, 4 );
setGradient( Q::Panel, Qt::transparent );
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()