combobox input handling improved ( wheel, more keys )
This commit is contained in:
parent
04c50fc301
commit
dae0cd7b1b
|
@ -290,9 +290,9 @@ void Editor::setupComboBox()
|
|||
m_pal.surfaceVariant, m_pal.focusOpacity );
|
||||
setGradient( Q::Panel | Q::Focused, focusColor );
|
||||
|
||||
const auto pressedColor = flattenedColor( m_pal.onSurfaceVariant,
|
||||
const auto activeColor = flattenedColor( m_pal.onSurfaceVariant,
|
||||
m_pal.surfaceVariant, m_pal.pressedOpacity );
|
||||
setGradient( Q::Panel | Q::Pressed, pressedColor );
|
||||
setGradient( Q::Panel | Q::PopupOpen, activeColor );
|
||||
|
||||
setStrutSize( Q::Graphic, 24_dp, 24_dp );
|
||||
setGraphicRole( Q::Graphic, QskMaterial3Skin::GraphicRoleOnSurface );
|
||||
|
@ -300,9 +300,9 @@ void Editor::setupComboBox()
|
|||
setColor( Q::Text, m_pal.onSurface );
|
||||
setFontRole( Q::Text, QskMaterial3Skin::M3BodyMedium );
|
||||
|
||||
setStrutSize( Q::OpenMenuGraphic, 12_dp, 12_dp );
|
||||
setGraphicRole( Q::OpenMenuGraphic, QskMaterial3Skin::GraphicRoleOnSurface );
|
||||
setAlignment( Q::OpenMenuGraphic, Qt::AlignRight | Qt::AlignVCenter );
|
||||
setStrutSize( Q::PopupIndicator, 12_dp, 12_dp );
|
||||
setGraphicRole( Q::PopupIndicator, QskMaterial3Skin::GraphicRoleOnSurface );
|
||||
setAlignment( Q::PopupIndicator, Qt::AlignRight | Qt::AlignVCenter );
|
||||
|
||||
|
||||
const auto disabledPanelColor = QskRgb::toTransparentF( m_pal.onSurface, 0.04 );
|
||||
|
@ -313,10 +313,10 @@ void Editor::setupComboBox()
|
|||
|
||||
setColor( Q::Text | Q::Disabled, m_pal.onSurface38 );
|
||||
|
||||
setGraphicRole( Q::OpenMenuGraphic, QskMaterial3Skin::GraphicRoleOnSurface38 );
|
||||
setGraphicRole( Q::PopupIndicator, QskMaterial3Skin::GraphicRoleOnSurface38 );
|
||||
|
||||
setSymbol( Q::OpenMenuGraphic, symbol( "combo-box-arrow-closed" ) );
|
||||
setSymbol( Q::OpenMenuGraphic | Q::PopupOpen, symbol( "combo-box-arrow-open" ) );
|
||||
setSymbol( Q::PopupIndicator, symbol( "combo-box-arrow-closed" ) );
|
||||
setSymbol( Q::PopupIndicator | Q::PopupOpen, symbol( "combo-box-arrow-open" ) );
|
||||
}
|
||||
|
||||
void Editor::setupBox()
|
||||
|
|
|
@ -382,14 +382,14 @@ void Editor::setupComboBox()
|
|||
setStrutSize( Q::Graphic, 24_dp, 24_dp );
|
||||
setGraphicRole( Q::Graphic | Q::Disabled, DisabledSymbol );
|
||||
|
||||
setStrutSize( Q::OpenMenuGraphic, 15_dp, 15_dp );
|
||||
setGraphicRole( Q::OpenMenuGraphic | Q::Disabled, DisabledSymbol );
|
||||
setStrutSize( Q::PopupIndicator, 15_dp, 15_dp );
|
||||
setGraphicRole( Q::PopupIndicator | Q::Disabled, DisabledSymbol );
|
||||
|
||||
setAlignment( Q::OpenMenuGraphic, Qt::AlignRight | Qt::AlignVCenter );
|
||||
setAlignment( Q::PopupIndicator, Qt::AlignRight | Qt::AlignVCenter );
|
||||
|
||||
setSymbol( Q::OpenMenuGraphic,
|
||||
setSymbol( Q::PopupIndicator,
|
||||
QskStandardSymbol::graphic( QskStandardSymbol::TriangleDown ) );
|
||||
setSymbol( Q::OpenMenuGraphic | Q::PopupOpen,
|
||||
setSymbol( Q::PopupIndicator | Q::PopupOpen,
|
||||
QskStandardSymbol::graphic( QskStandardSymbol::TriangleUp ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -8,17 +8,45 @@
|
|||
#include "QskGraphic.h"
|
||||
#include "QskMenu.h"
|
||||
#include "QskTextOptions.h"
|
||||
#include "QskEvent.h"
|
||||
|
||||
#include <qquickwindow.h>
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qguiapplication_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
#include <qpa/qplatformtheme.h>
|
||||
|
||||
QSK_SUBCONTROL( QskComboBox, Panel )
|
||||
QSK_SUBCONTROL( QskComboBox, Graphic )
|
||||
QSK_SUBCONTROL( QskComboBox, Text )
|
||||
QSK_SUBCONTROL( QskComboBox, OpenMenuGraphic )
|
||||
QSK_SUBCONTROL( QskComboBox, PopupIndicator )
|
||||
QSK_SUBCONTROL( QskComboBox, Splash )
|
||||
|
||||
QSK_SYSTEM_STATE( QskComboBox, Pressed, QskAspect::FirstSystemState << 1 )
|
||||
QSK_SYSTEM_STATE( QskComboBox, PopupOpen, QskAspect::FirstSystemState << 2 )
|
||||
QSK_SYSTEM_STATE( QskComboBox, PopupOpen, QskAspect::FirstSystemState << 1 )
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
|
||||
static inline QList< Qt::Key > qskButtonPressKeys()
|
||||
{
|
||||
const auto hint = QGuiApplicationPrivate::platformTheme()->themeHint(
|
||||
QPlatformTheme::ButtonPressKeys );
|
||||
|
||||
return hint.value< QList< Qt::Key > >();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline QList< Qt::Key > qskButtonPressKeys()
|
||||
{
|
||||
static const QList< Qt::Key > keys =
|
||||
{ Qt::Key_Space, Qt::Key_Enter, Qt::Key_Return, Qt::Key_Select };
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
class QskComboBox::PrivateData
|
||||
{
|
||||
|
@ -56,63 +84,34 @@ QskComboBox::QskComboBox( QQuickItem* parent )
|
|||
|
||||
setAcceptHoverEvents( true );
|
||||
|
||||
connect( m_data->menu, &QskMenu::currentIndexChanged,
|
||||
this, &QskComboBox::currentIndexChanged );
|
||||
connect( m_data->menu, &QskMenu::triggered,
|
||||
this, &QskComboBox::activated );
|
||||
|
||||
connect( m_data->menu, &QskMenu::currentIndexChanged,
|
||||
this, &QQuickItem::update );
|
||||
this, &QskComboBox::showOption );
|
||||
|
||||
connect( m_data->menu, &QskMenu::countChanged,
|
||||
this, &QskComboBox::countChanged );
|
||||
|
||||
connect( this, &QskComboBox::currentIndexChanged,
|
||||
this, &QskControl::focusIndicatorRectChanged );
|
||||
|
||||
connect( m_data->menu, &QskMenu::closed, this,
|
||||
[ this ]() { setPopupOpen( false ); setFocus( true ); } );
|
||||
|
||||
connect( this, &QskComboBox::pressed, this, &QskComboBox::togglePopup );
|
||||
}
|
||||
|
||||
QskComboBox::~QskComboBox()
|
||||
{
|
||||
}
|
||||
|
||||
void QskComboBox::setPressed( bool on )
|
||||
{
|
||||
if ( on == isPressed() )
|
||||
return;
|
||||
|
||||
setSkinStateFlag( Pressed, on );
|
||||
Q_EMIT pressedChanged( on );
|
||||
|
||||
if ( on )
|
||||
Q_EMIT pressed();
|
||||
else
|
||||
Q_EMIT released();
|
||||
}
|
||||
|
||||
bool QskComboBox::isPressed() const
|
||||
{
|
||||
return hasSkinState( Pressed );
|
||||
}
|
||||
|
||||
void QskComboBox::setPopupOpen( bool on )
|
||||
{
|
||||
if ( on == isPopupOpen() )
|
||||
return;
|
||||
|
||||
if( on )
|
||||
{
|
||||
openPopup();
|
||||
}
|
||||
else
|
||||
{
|
||||
closePopup();
|
||||
}
|
||||
|
||||
setSkinStateFlag( PopupOpen, on );
|
||||
Q_EMIT popupOpenChanged( on );
|
||||
|
||||
if( on )
|
||||
openPopup();
|
||||
else
|
||||
closePopup();
|
||||
}
|
||||
|
||||
bool QskComboBox::isPopupOpen() const
|
||||
|
@ -172,7 +171,7 @@ void QskComboBox::setPlaceholderText( const QString& text )
|
|||
Q_EMIT placeholderTextChanged( text );
|
||||
}
|
||||
|
||||
QString QskComboBox::text() const
|
||||
QString QskComboBox::currentText() const
|
||||
{
|
||||
const int index = currentIndex();
|
||||
if( index >= 0 )
|
||||
|
@ -184,11 +183,6 @@ QString QskComboBox::text() const
|
|||
return placeholderText();
|
||||
}
|
||||
|
||||
void QskComboBox::togglePopup()
|
||||
{
|
||||
setPopupOpen( !isPopupOpen() );
|
||||
}
|
||||
|
||||
void QskComboBox::openPopup()
|
||||
{
|
||||
const auto cr = contentsRect();
|
||||
|
@ -209,39 +203,64 @@ void QskComboBox::closePopup()
|
|||
|
||||
void QskComboBox::mousePressEvent( QMouseEvent* )
|
||||
{
|
||||
setPressed( true );
|
||||
}
|
||||
|
||||
void QskComboBox::mouseUngrabEvent()
|
||||
{
|
||||
setPressed( false );
|
||||
setPopupOpen( true );
|
||||
}
|
||||
|
||||
void QskComboBox::mouseReleaseEvent( QMouseEvent* )
|
||||
{
|
||||
releaseButton();
|
||||
}
|
||||
|
||||
void QskComboBox::keyPressEvent( QKeyEvent* event )
|
||||
{
|
||||
switch ( event->key() )
|
||||
if ( qskButtonPressKeys().contains( event->key() ) )
|
||||
{
|
||||
case Qt::Key_Select:
|
||||
case Qt::Key_Space:
|
||||
if ( !event->isAutoRepeat() )
|
||||
{
|
||||
if ( !event->isAutoRepeat() )
|
||||
{
|
||||
setPressed( true );
|
||||
// calling release button here, because
|
||||
// we will never get the key release event
|
||||
// when the menu is opened:
|
||||
releaseButton();
|
||||
}
|
||||
|
||||
setPopupOpen( true );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch( event->key() )
|
||||
{
|
||||
#if 0
|
||||
case Qt::Key_F4:
|
||||
{
|
||||
// QComboBox does this ???
|
||||
setPopupOpen( true );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
case Qt::Key_Up:
|
||||
case Qt::Key_PageUp:
|
||||
{
|
||||
increment( -1 );
|
||||
return;
|
||||
}
|
||||
case Qt::Key_Down:
|
||||
case Qt::Key_PageDown:
|
||||
{
|
||||
increment( 1 );
|
||||
return;
|
||||
}
|
||||
case Qt::Key_Home:
|
||||
{
|
||||
if ( count() > 0 )
|
||||
setCurrentIndex( 0 );
|
||||
return;
|
||||
}
|
||||
case Qt::Key_End:
|
||||
{
|
||||
if ( count() > 0 )
|
||||
setCurrentIndex( count() - 1 );
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
// searching option by key TODO ...
|
||||
break;
|
||||
}
|
||||
|
||||
Inherited::keyPressEvent( event );
|
||||
}
|
||||
|
||||
|
@ -250,6 +269,11 @@ void QskComboBox::keyReleaseEvent( QKeyEvent* event )
|
|||
Inherited::keyReleaseEvent( event );
|
||||
}
|
||||
|
||||
void QskComboBox::wheelEvent( QWheelEvent* event )
|
||||
{
|
||||
increment( -qRound( qskWheelSteps( event ) ) );
|
||||
}
|
||||
|
||||
void QskComboBox::clear()
|
||||
{
|
||||
m_data->menu->clear();
|
||||
|
@ -271,13 +295,29 @@ int QskComboBox::count() const
|
|||
return m_data->menu->count();
|
||||
}
|
||||
|
||||
void QskComboBox::releaseButton()
|
||||
void QskComboBox::showOption( int index )
|
||||
{
|
||||
if ( !isPressed() )
|
||||
update();
|
||||
Q_EMIT currentIndexChanged( index );
|
||||
}
|
||||
|
||||
void QskComboBox::increment( int steps )
|
||||
{
|
||||
if ( count() == 0 )
|
||||
return;
|
||||
|
||||
setPressed( false );
|
||||
Q_EMIT clicked();
|
||||
if ( currentIndex() == -1 && steps < 0 )
|
||||
steps++;
|
||||
|
||||
int nextIndex = ( currentIndex() + steps ) % count();
|
||||
if ( nextIndex < 0 )
|
||||
nextIndex += count();
|
||||
|
||||
if ( nextIndex != currentIndex() )
|
||||
{
|
||||
m_data->menu->setCurrentIndex( nextIndex );
|
||||
Q_EMIT activated( nextIndex );
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_QskComboBox.cpp"
|
||||
|
|
|
@ -17,6 +17,8 @@ class QSK_EXPORT QskComboBox : public QskControl
|
|||
Q_PROPERTY( int currentIndex READ currentIndex
|
||||
WRITE setCurrentIndex NOTIFY currentIndexChanged )
|
||||
|
||||
Q_PROPERTY( QString currentText READ currentText )
|
||||
|
||||
Q_PROPERTY( int count READ count NOTIFY countChanged )
|
||||
|
||||
Q_PROPERTY( QString placeholderText READ placeholderText
|
||||
|
@ -25,17 +27,14 @@ class QSK_EXPORT QskComboBox : public QskControl
|
|||
using Inherited = QskControl;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Panel, Graphic, Text, OpenMenuGraphic, Splash )
|
||||
QSK_STATES( Pressed, PopupOpen )
|
||||
QSK_SUBCONTROLS( Panel, Graphic, Text, PopupIndicator, Splash )
|
||||
QSK_STATES( PopupOpen )
|
||||
|
||||
QskComboBox( QQuickItem* parent = nullptr );
|
||||
|
||||
~QskComboBox() override;
|
||||
|
||||
void setPressed( bool on );
|
||||
bool isPressed() const;
|
||||
|
||||
void setPopupOpen( bool on );
|
||||
void setPopupOpen( bool );
|
||||
bool isPopupOpen() const;
|
||||
|
||||
QskGraphic graphic() const;
|
||||
|
@ -48,46 +47,40 @@ class QSK_EXPORT QskComboBox : public QskControl
|
|||
void clear();
|
||||
|
||||
int currentIndex() const;
|
||||
QString currentText() const;
|
||||
|
||||
int count() const;
|
||||
|
||||
QVariantList optionAt( int ) const;
|
||||
|
||||
QString placeholderText() const;
|
||||
void setPlaceholderText( const QString& );
|
||||
|
||||
QString text() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void togglePopup();
|
||||
virtual void openPopup();
|
||||
virtual void closePopup();
|
||||
|
||||
void setCurrentIndex( int );
|
||||
|
||||
Q_SIGNALS:
|
||||
void activated( int );
|
||||
void currentIndexChanged( int );
|
||||
|
||||
void countChanged();
|
||||
|
||||
void pressed();
|
||||
void released();
|
||||
void clicked();
|
||||
|
||||
void pressedChanged( bool );
|
||||
void popupOpenChanged( bool );
|
||||
|
||||
void placeholderTextChanged( const QString& );
|
||||
|
||||
protected:
|
||||
void mousePressEvent( QMouseEvent* ) override;
|
||||
void mouseUngrabEvent() override;
|
||||
void mouseReleaseEvent( QMouseEvent* ) override;
|
||||
|
||||
void keyPressEvent( QKeyEvent* ) override;
|
||||
void keyReleaseEvent( QKeyEvent* ) override;
|
||||
|
||||
void wheelEvent( QWheelEvent* ) override;
|
||||
|
||||
virtual void openPopup();
|
||||
virtual void closePopup();
|
||||
|
||||
private:
|
||||
void showOption( int );
|
||||
void releaseButton();
|
||||
void increment( int );
|
||||
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace
|
|||
{
|
||||
if( std::is_same< T, QString >() )
|
||||
{
|
||||
return box->text();
|
||||
return box->currentText();
|
||||
}
|
||||
|
||||
const int index = box->currentIndex();
|
||||
|
@ -56,7 +56,8 @@ namespace
|
|||
QskComboBox::Text, qskValueAt< QString >( box ),
|
||||
QskComboBox::Graphic, qskValueAt< QskGraphic >( box ).defaultSize() );
|
||||
|
||||
const auto alignment = box->alignmentHint( QskComboBox::Panel, Qt::AlignLeft );
|
||||
const auto alignment = box->alignmentHint(
|
||||
QskComboBox::Panel, Qt::AlignLeft );
|
||||
setFixedContent( QskComboBox::Text, Qt::Horizontal, alignment );
|
||||
}
|
||||
};
|
||||
|
@ -65,7 +66,8 @@ namespace
|
|||
QskComboBoxSkinlet::QskComboBoxSkinlet( QskSkin* skin )
|
||||
: Inherited( skin )
|
||||
{
|
||||
setNodeRoles( { PanelRole, SplashRole, GraphicRole, TextRole, OpenMenuGraphicRole } );
|
||||
setNodeRoles( { PanelRole, SplashRole,
|
||||
GraphicRole, TextRole, PopupIndicatorRole } );
|
||||
}
|
||||
|
||||
QskComboBoxSkinlet::~QskComboBoxSkinlet() = default;
|
||||
|
@ -93,10 +95,10 @@ QRectF QskComboBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
|
|||
return layoutEngine.subControlRect( subControl );
|
||||
}
|
||||
|
||||
if( subControl == Q::OpenMenuGraphic )
|
||||
if( subControl == Q::PopupIndicator )
|
||||
{
|
||||
auto rect = box->innerBox( Q::Panel, contentsRect );
|
||||
const auto size = box->strutSizeHint( Q::OpenMenuGraphic );
|
||||
const auto size = box->strutSizeHint( Q::PopupIndicator );
|
||||
rect.setLeft( rect.right() - size.width() );
|
||||
return rect;
|
||||
}
|
||||
|
@ -122,8 +124,8 @@ QSGNode* QskComboBoxSkinlet::updateSubNode(
|
|||
case TextRole:
|
||||
return updateTextNode( box, node );
|
||||
|
||||
case OpenMenuGraphicRole:
|
||||
return updateSymbolNode( box, node, Q::OpenMenuGraphic );
|
||||
case PopupIndicatorRole:
|
||||
return updateSymbolNode( box, node, Q::PopupIndicator );
|
||||
}
|
||||
|
||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||
|
@ -144,7 +146,7 @@ QRectF QskComboBoxSkinlet::splashRect(
|
|||
const auto pos = box->positionHint( Q::Splash );
|
||||
const qreal w = 2.0 * rect.width() * ratio;
|
||||
|
||||
rect.setX( pos - 0.5 * w );
|
||||
rect.setX( pos - 0.5 * w );
|
||||
rect.setWidth( w );
|
||||
}
|
||||
|
||||
|
@ -165,7 +167,7 @@ QSGNode* QskComboBoxSkinlet::updateTextNode(
|
|||
const auto alignment = box->alignmentHint( Q::Text, Qt::AlignLeft | Qt::AlignVCenter );
|
||||
|
||||
return QskSkinlet::updateTextNode( box, node, rect,
|
||||
alignment, box->text(), Q::Text );
|
||||
alignment, box->currentText(), Q::Text );
|
||||
}
|
||||
|
||||
QSGNode* QskComboBoxSkinlet::updateSplashNode(
|
||||
|
@ -210,7 +212,7 @@ QSizeF QskComboBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
|
|||
auto size = layoutEngine.sizeHint( which, QSizeF() );
|
||||
|
||||
const auto spacingHint = box->spacingHint( Q::Panel );
|
||||
const auto menuGraphicHint = box->strutSizeHint( Q::OpenMenuGraphic );
|
||||
const auto menuGraphicHint = box->strutSizeHint( Q::PopupIndicator );
|
||||
|
||||
size.rwidth() += spacingHint + menuGraphicHint.width();
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class QSK_EXPORT QskComboBoxSkinlet : public QskSkinlet
|
|||
PanelRole,
|
||||
GraphicRole,
|
||||
TextRole,
|
||||
OpenMenuGraphicRole,
|
||||
PopupIndicatorRole,
|
||||
SplashRole,
|
||||
|
||||
RoleCount
|
||||
|
|
Loading…
Reference in New Issue