QskSpinBox work in progress
This commit is contained in:
parent
06704511d2
commit
06ba85605b
|
@ -53,8 +53,8 @@ void SpinBoxPage::populate()
|
||||||
spinboxes << spinbox;
|
spinboxes << spinbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto strutInc = spinboxes[ 0 ]->strutSizeHint( QskSpinBox::IncrementPanel );
|
const auto strutInc = spinboxes[ 0 ]->strutSizeHint( QskSpinBox::UpPanel );
|
||||||
const auto strutDec = spinboxes[ 0 ]->strutSizeHint( QskSpinBox::DecrementPanel );
|
const auto strutDec = spinboxes[ 0 ]->strutSizeHint( QskSpinBox::DownPanel );
|
||||||
|
|
||||||
auto* const columnIncW = new QskLinearBox( Qt::Vertical, this );
|
auto* const columnIncW = new QskLinearBox( Qt::Vertical, this );
|
||||||
auto* const sliderIncW = new QskSlider( Qt::Vertical, columnIncW );
|
auto* const sliderIncW = new QskSlider( Qt::Vertical, columnIncW );
|
||||||
|
@ -93,8 +93,8 @@ void SpinBoxPage::populate()
|
||||||
const auto decSize = QSizeF{ sliderDecW->value(), sliderDecH->value() };
|
const auto decSize = QSizeF{ sliderDecW->value(), sliderDecH->value() };
|
||||||
for ( auto* spinbox : spinboxes )
|
for ( auto* spinbox : spinboxes )
|
||||||
{
|
{
|
||||||
spinbox->setStrutSizeHint( QskSpinBox::IncrementPanel, incSize );
|
spinbox->setStrutSizeHint( QskSpinBox::UpPanel, incSize );
|
||||||
spinbox->setStrutSizeHint( QskSpinBox::DecrementPanel, decSize );
|
spinbox->setStrutSizeHint( QskSpinBox::DownPanel, decSize );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -818,39 +818,37 @@ void Editor::setupSpinBox()
|
||||||
setSpacing( Q::Panel, 4_dp );
|
setSpacing( Q::Panel, 4_dp );
|
||||||
|
|
||||||
setStrutSize( Q::TextPanel, 80_dp, 40_dp );
|
setStrutSize( Q::TextPanel, 80_dp, 40_dp );
|
||||||
setStrutSize( Q::IncrementPanel, 40_dp,40_dp );
|
setStrutSize( Q::UpPanel, 40_dp,40_dp );
|
||||||
setStrutSize( Q::DecrementPanel, 40_dp, 40_dp );
|
setStrutSize( Q::DownPanel, 40_dp, 40_dp );
|
||||||
|
|
||||||
setAlignment( Q::Panel, Qt::AlignHCenter );
|
setAlignment( Q::Panel, Qt::AlignHCenter );
|
||||||
setAlignment( Q::Text, Qt::AlignCenter );
|
setAlignment( Q::Text, Qt::AlignCenter );
|
||||||
|
|
||||||
for( const auto& state : { Q::DecrementPanel, Q::IncrementPanel, Q::TextPanel } )
|
for( const auto subControl : { Q::DownPanel, Q::UpPanel, Q::TextPanel } )
|
||||||
{
|
{
|
||||||
setBoxShape( state, 4_dp );
|
setBoxShape( subControl, 4_dp );
|
||||||
setBoxBorderMetrics( state, 1_dp );
|
setBoxBorderMetrics( subControl, 1_dp );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( const auto& state : { Q::DecrementPanel, Q::IncrementPanel } )
|
for( const auto subControl : { Q::DownPanel, Q::UpPanel } )
|
||||||
{
|
{
|
||||||
setGradient( state, m_pal.primary );
|
setGradient( subControl, m_pal.primary );
|
||||||
setGradient( state | Q::Disabled, m_pal.onSurface12 );
|
setGradient( subControl | Q::Disabled, m_pal.onSurface12 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
const auto focusColor = flattenedColor( m_pal.onPrimary, m_pal.primary, 0.12 );
|
const auto focusColor = flattenedColor( m_pal.onPrimary, m_pal.primary, 0.12 );
|
||||||
setGradient( state | Q::Focused, focusColor );
|
|
||||||
setGradient( state | Q::Pressed, focusColor );
|
|
||||||
|
|
||||||
const auto hoverColor = flattenedColor( m_pal.onPrimary, m_pal.primary, 0.08 );
|
setGradient( Q::DownPanel | Q::Decreasing, focusColor );
|
||||||
setGradient( state | Q::Hovered, hoverColor );
|
setGradient( Q::UpPanel | Q::Increasing, focusColor );
|
||||||
setShadowMetrics( state | Q::Hovered, m_pal.elevation1 );
|
|
||||||
setShadowColor( state | Q::Hovered, m_pal.shadow );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for( const auto& state : { Q::DecrementIndicator, Q::IncrementIndicator } )
|
for( const auto subControl : { Q::DownIndicator, Q::UpIndicator } )
|
||||||
{
|
{
|
||||||
setColor( state, m_pal.onPrimary );
|
setColor( subControl, m_pal.onPrimary );
|
||||||
setColor( state | Q::Disabled, m_pal.onSurface38 );
|
setColor( subControl | Q::Disabled, m_pal.onSurface38 );
|
||||||
setAlignment(state, Qt::AlignCenter );
|
setAlignment( subControl, Qt::AlignCenter );
|
||||||
setFontRole( state, QskMaterial3Skin::M3LabelLarge );
|
setFontRole( subControl, QskMaterial3Skin::M3LabelLarge );
|
||||||
}
|
}
|
||||||
|
|
||||||
setColor( Q::Text, m_pal.onBackground );
|
setColor( Q::Text, m_pal.onBackground );
|
||||||
|
@ -864,12 +862,6 @@ void Editor::setupSpinBox()
|
||||||
setBoxBorderMetrics( Q::TextPanel | Q::Focused, 0, 0, 0, 2_dp );
|
setBoxBorderMetrics( Q::TextPanel | Q::Focused, 0, 0, 0, 2_dp );
|
||||||
setBoxBorderColors( Q::TextPanel | Q::Focused, m_pal.primary );
|
setBoxBorderColors( Q::TextPanel | Q::Focused, m_pal.primary );
|
||||||
|
|
||||||
// setBoxBorderMetrics( Q::TextPanel | Q::Editing, 0, 0, 0, 2_dp );
|
|
||||||
// setBoxBorderColors( Q::TextPanel | Q::Editing, m_pal.primary );
|
|
||||||
|
|
||||||
setBoxBorderMetrics( Q::TextPanel | Q::Hovered, 0, 0, 0, 1_dp );
|
|
||||||
setBoxBorderColors( Q::TextPanel | Q::Hovered, m_pal.onSurface );
|
|
||||||
|
|
||||||
setGradient( Q::TextPanel, m_pal.surfaceVariant );
|
setGradient( Q::TextPanel, m_pal.surfaceVariant );
|
||||||
|
|
||||||
const auto c1 = QskRgb::toTransparentF( m_pal.onSurface, 0.04 );
|
const auto c1 = QskRgb::toTransparentF( m_pal.onSurface, 0.04 );
|
||||||
|
|
|
@ -4,77 +4,111 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "QskSpinBox.h"
|
#include "QskSpinBox.h"
|
||||||
#include "QskIntervalF.h"
|
|
||||||
#include "QskEvent.h"
|
#include "QskEvent.h"
|
||||||
|
|
||||||
|
#include <qbasictimer.h>
|
||||||
|
|
||||||
QSK_SUBCONTROL( QskSpinBox, Panel )
|
QSK_SUBCONTROL( QskSpinBox, Panel )
|
||||||
|
|
||||||
QSK_SUBCONTROL( QskSpinBox, TextPanel )
|
QSK_SUBCONTROL( QskSpinBox, TextPanel )
|
||||||
QSK_SUBCONTROL( QskSpinBox, Text )
|
QSK_SUBCONTROL( QskSpinBox, Text )
|
||||||
|
|
||||||
QSK_SUBCONTROL( QskSpinBox, IncrementPanel )
|
QSK_SUBCONTROL( QskSpinBox, UpPanel )
|
||||||
QSK_SUBCONTROL( QskSpinBox, IncrementIndicator )
|
QSK_SUBCONTROL( QskSpinBox, UpIndicator )
|
||||||
|
|
||||||
QSK_SUBCONTROL( QskSpinBox, DecrementPanel )
|
QSK_SUBCONTROL( QskSpinBox, DownPanel )
|
||||||
QSK_SUBCONTROL( QskSpinBox, DecrementIndicator )
|
QSK_SUBCONTROL( QskSpinBox, DownIndicator )
|
||||||
|
|
||||||
QSK_SYSTEM_STATE( QskSpinBox, Pressed, ( QskAspect::QskAspect::FirstSystemState << 0 ) )
|
QSK_SYSTEM_STATE( QskSpinBox, Increasing, ( QskAspect::FirstSystemState << 2 ) )
|
||||||
|
QSK_SYSTEM_STATE( QskSpinBox, Decreasing, ( QskAspect::FirstSystemState << 3 ) )
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
enum
|
inline QskAspect::Subcontrol buttonAt( const QskSpinBox* spinBox, const QPointF& pos )
|
||||||
{
|
{
|
||||||
ButtonDecrement = -1,
|
if ( spinBox->subControlRect( QskSpinBox::UpPanel ).contains( pos ) )
|
||||||
ButtonNone = 0,
|
return QskSpinBox::UpPanel;
|
||||||
ButtonIncrement = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
inline int buttonAt( const QskSpinBox* spinBox, const QPointF& pos )
|
if ( spinBox->subControlRect( QskSpinBox::DownPanel ).contains( pos ) )
|
||||||
{
|
return QskSpinBox::DownPanel;
|
||||||
if ( spinBox->subControlRect( QskSpinBox::IncrementPanel ).contains( pos ) )
|
|
||||||
return ButtonIncrement;
|
|
||||||
|
|
||||||
if ( spinBox->subControlRect( QskSpinBox::DecrementPanel ).contains( pos ) )
|
return QskAspect::NoSubcontrol;
|
||||||
return ButtonDecrement;
|
|
||||||
|
|
||||||
return ButtonNone;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class QskSpinBox::PrivateData
|
class QskSpinBox::PrivateData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline void setPressed( QskSpinBox* spinBox, int button )
|
PrivateData()
|
||||||
|
: buttons( true )
|
||||||
|
, tracking( true )
|
||||||
|
, wrapping( false )
|
||||||
|
, accelerating( false )
|
||||||
{
|
{
|
||||||
if ( pressedButton != button )
|
|
||||||
{
|
|
||||||
pressedButton = button;
|
|
||||||
spinBox->update();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void setHovered( QskSpinBox* spinBox, int button )
|
inline void setAutoRepeat( QskSpinBox* spinBox, qreal offset )
|
||||||
{
|
{
|
||||||
if ( hoveredButton != button )
|
this->autoRepeatIncrement = offset;
|
||||||
|
this->key = Qt::Key_unknown;
|
||||||
|
|
||||||
|
if( offset < 0.0 )
|
||||||
{
|
{
|
||||||
hoveredButton = button;
|
if ( spinBox->hasSkinState( QskSpinBox::Increasing ) )
|
||||||
spinBox->update();
|
spinBox->setSkinStateFlag( QskSpinBox::Increasing, false );
|
||||||
|
|
||||||
|
if ( !spinBox->hasSkinState( QskSpinBox::Decreasing ) )
|
||||||
|
{
|
||||||
|
spinBox->setSkinStateFlag( QskSpinBox::Decreasing, true );
|
||||||
|
this->repeatTimer.start( autoRepeatDelay, spinBox );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( offset > 0.0 )
|
||||||
|
{
|
||||||
|
if ( spinBox->hasSkinState( QskSpinBox::Decreasing ) )
|
||||||
|
spinBox->setSkinStateFlag( QskSpinBox::Decreasing, false );
|
||||||
|
|
||||||
|
if ( !spinBox->hasSkinState( QskSpinBox::Increasing ) )
|
||||||
|
{
|
||||||
|
spinBox->setSkinStateFlag( QskSpinBox::Increasing, true );
|
||||||
|
this->repeatTimer.start( autoRepeatDelay, spinBox );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spinBox->setSkinStateFlag( QskSpinBox::Decreasing, false );
|
||||||
|
spinBox->setSkinStateFlag( QskSpinBox::Increasing, false );
|
||||||
|
|
||||||
|
this->repeatTimer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
int pressedButton = ButtonNone;
|
int autoRepeatDelay = 300;
|
||||||
int hoveredButton = ButtonNone;
|
int autoRepeatInterval = 100;
|
||||||
|
|
||||||
// int decimals; ???
|
qreal autoRepeatIncrement = 0.0;
|
||||||
|
|
||||||
|
QBasicTimer repeatTimer;
|
||||||
|
|
||||||
|
int key = Qt::Key_unknown;
|
||||||
|
|
||||||
|
bool buttons : 1;
|
||||||
|
bool tracking : 1;
|
||||||
|
bool wrapping : 1;
|
||||||
|
bool accelerating : 1; // not yet implemented: TODO ...
|
||||||
};
|
};
|
||||||
|
|
||||||
QskSpinBox::QskSpinBox( QQuickItem* const parent )
|
QskSpinBox::QskSpinBox( QQuickItem* parent )
|
||||||
: Inherited( parent )
|
: Inherited( parent )
|
||||||
, m_data( new PrivateData )
|
, m_data( new PrivateData )
|
||||||
{
|
{
|
||||||
|
initSizePolicy( QskSizePolicy::Minimum, QskSizePolicy::Fixed );
|
||||||
|
|
||||||
setBoundaries( 0.0, 99.99 ); // this is what QDoubleSpinBox does
|
setBoundaries( 0.0, 99.99 ); // this is what QDoubleSpinBox does
|
||||||
|
|
||||||
setAcceptHoverEvents( true );
|
|
||||||
setAcceptedMouseButtons( Qt::LeftButton );
|
setAcceptedMouseButtons( Qt::LeftButton );
|
||||||
setFocusPolicy( Qt::StrongFocus );
|
setFocusPolicy( Qt::StrongFocus );
|
||||||
}
|
}
|
||||||
|
@ -83,29 +117,80 @@ QskSpinBox::~QskSpinBox()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSpinBox::hoverEnterEvent( QHoverEvent* )
|
void QskSpinBox::setButtons( bool on )
|
||||||
{
|
{
|
||||||
|
if ( on != m_data->buttons )
|
||||||
|
{
|
||||||
|
m_data->buttons = on;
|
||||||
|
Q_EMIT buttonsChanged( on );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSpinBox::hoverLeaveEvent( QHoverEvent* )
|
bool QskSpinBox::hasButtons() const
|
||||||
{
|
{
|
||||||
m_data->setHovered( this, ButtonNone );
|
return m_data->buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSpinBox::hoverMoveEvent( QHoverEvent* event )
|
void QskSpinBox::setTracking( bool on )
|
||||||
{
|
{
|
||||||
const auto button = buttonAt( this, qskHoverPosition( event ) );
|
if ( on != m_data->tracking )
|
||||||
m_data->setHovered( this, button );
|
{
|
||||||
|
m_data->tracking = on;
|
||||||
|
Q_EMIT trackingChanged( on );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QskSpinBox::isTracking() const
|
||||||
|
{
|
||||||
|
return m_data->tracking;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskSpinBox::setWrapping( bool on )
|
||||||
|
{
|
||||||
|
if ( on != m_data->wrapping )
|
||||||
|
{
|
||||||
|
m_data->wrapping = on;
|
||||||
|
Q_EMIT wrappingChanged( on );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QskSpinBox::isWrapping() const
|
||||||
|
{
|
||||||
|
return m_data->wrapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskSpinBox::setAccelerating( bool on )
|
||||||
|
{
|
||||||
|
if ( on != m_data->accelerating )
|
||||||
|
{
|
||||||
|
m_data->accelerating = on;
|
||||||
|
Q_EMIT acceleratingChanged( on );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QskSpinBox::isAccelerating() const
|
||||||
|
{
|
||||||
|
return m_data->accelerating;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSpinBox::mousePressEvent( QMouseEvent* event )
|
void QskSpinBox::mousePressEvent( QMouseEvent* event )
|
||||||
{
|
{
|
||||||
if ( const auto button = buttonAt( this, qskMousePosition( event ) ) )
|
if ( !isReadOnly() )
|
||||||
{
|
{
|
||||||
m_data->setPressed( this, button );
|
if ( auto subcontrol = buttonAt( this, qskMousePosition( event ) ) )
|
||||||
increment( stepSize() * button );
|
{
|
||||||
|
if ( !m_data->repeatTimer.isActive() )
|
||||||
|
{
|
||||||
|
auto increment = ( event->modifiers() == Qt::ControlModifier )
|
||||||
|
? stepSize() : pageSize();
|
||||||
|
|
||||||
return;
|
if ( subcontrol == QskSpinBox::DownPanel )
|
||||||
|
increment = -increment;
|
||||||
|
|
||||||
|
m_data->setAutoRepeat( this, increment );
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Inherited::mousePressEvent( event );
|
Inherited::mousePressEvent( event );
|
||||||
|
@ -113,65 +198,55 @@ void QskSpinBox::mousePressEvent( QMouseEvent* event )
|
||||||
|
|
||||||
void QskSpinBox::mouseReleaseEvent( QMouseEvent* )
|
void QskSpinBox::mouseReleaseEvent( QMouseEvent* )
|
||||||
{
|
{
|
||||||
m_data->setPressed( this, ButtonNone );
|
m_data->setAutoRepeat( this, 0.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSpinBox::keyPressEvent( QKeyEvent* const event )
|
void QskSpinBox::keyPressEvent( QKeyEvent* event )
|
||||||
{
|
{
|
||||||
switch ( event->key() )
|
if ( !isReadOnly() && !m_data->repeatTimer.isActive() )
|
||||||
{
|
{
|
||||||
case Qt::Key_Minus:
|
const auto offset = incrementForKey( event );
|
||||||
case Qt::Key_Down:
|
if ( offset != 0.0 )
|
||||||
case Qt::Key_Left:
|
|
||||||
{
|
{
|
||||||
increment( -stepSize() );
|
if ( !m_data->repeatTimer.isActive() )
|
||||||
m_data->setPressed( this, ButtonDecrement );
|
{
|
||||||
|
increment( offset );
|
||||||
|
|
||||||
|
m_data->setAutoRepeat( this, offset );
|
||||||
|
m_data->key = event->key();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Qt::Key_Plus:
|
|
||||||
case Qt::Key_Up:
|
|
||||||
case Qt::Key_Right:
|
|
||||||
{
|
|
||||||
increment( +stepSize() );
|
|
||||||
m_data->setPressed( this, ButtonIncrement );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
case Qt::Key_Select:
|
|
||||||
case Qt::Key_Space:
|
|
||||||
|
|
||||||
/*
|
|
||||||
All keys to navigate along the focus tab chain are not valid
|
|
||||||
for a spin box, as it accepts number inputs only. Guess this is why
|
|
||||||
QSpinBox goes straight into edit mode when receiving the focus
|
|
||||||
|
|
||||||
So once setting values by keyboard is implemented we have to decide
|
|
||||||
how to do it here. TODO ...
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Inherited::keyPressEvent( event );
|
Inherited::keyPressEvent( event );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSpinBox::keyReleaseEvent( QKeyEvent* const event )
|
void QskSpinBox::keyReleaseEvent( QKeyEvent* event )
|
||||||
{
|
{
|
||||||
m_data->setPressed( this, ButtonNone );
|
if ( m_data->key == event->key() )
|
||||||
|
{
|
||||||
|
m_data->setAutoRepeat( this, 0.0 );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Inherited::keyReleaseEvent( event );
|
Inherited::keyReleaseEvent( event );
|
||||||
}
|
}
|
||||||
|
|
||||||
int QskSpinBox::pressedButton() const
|
void QskSpinBox::timerEvent( QTimerEvent* event )
|
||||||
{
|
{
|
||||||
return m_data->pressedButton;
|
if ( event->timerId() == m_data->repeatTimer.timerId() )
|
||||||
|
{
|
||||||
|
if ( skinStates() & ( QskSpinBox::Increasing | QskSpinBox::Decreasing ) )
|
||||||
|
{
|
||||||
|
increment( m_data->autoRepeatIncrement );
|
||||||
|
m_data->repeatTimer.start( m_data->autoRepeatInterval, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Inherited::timerEvent( event );
|
||||||
}
|
}
|
||||||
|
|
||||||
int QskSpinBox::hoveredButton() const
|
#include "moc_QskSpinBox.cpp"
|
||||||
{
|
|
||||||
return m_data->hoveredButton;
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,36 +13,53 @@ class QSK_EXPORT QskSpinBox : public QskBoundedValueInput
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
using Inherited = QskBoundedValueInput;
|
using Inherited = QskBoundedValueInput;
|
||||||
|
|
||||||
|
Q_PROPERTY( bool wrapping READ isWrapping
|
||||||
|
WRITE setWrapping NOTIFY wrappingChanged )
|
||||||
|
|
||||||
|
Q_PROPERTY( bool tracking READ isTracking
|
||||||
|
WRITE setTracking NOTIFY trackingChanged )
|
||||||
|
|
||||||
|
Q_PROPERTY( bool accelerating READ isAccelerating
|
||||||
|
WRITE setAccelerating NOTIFY acceleratingChanged )
|
||||||
|
|
||||||
|
Q_PROPERTY( bool buttons READ hasButtons
|
||||||
|
WRITE setButtons NOTIFY buttonsChanged )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
QSK_SUBCONTROLS( Panel, TextPanel, Text,
|
QSK_SUBCONTROLS( Panel, TextPanel, Text,
|
||||||
IncrementPanel, IncrementIndicator, DecrementPanel, DecrementIndicator )
|
UpPanel, UpIndicator, DownPanel, DownIndicator )
|
||||||
|
|
||||||
QSK_STATES( Pressed )
|
QSK_STATES( Decreasing, Increasing )
|
||||||
|
|
||||||
QskSpinBox( QQuickItem* parent = nullptr );
|
QskSpinBox( QQuickItem* parent = nullptr );
|
||||||
~QskSpinBox() override;
|
~QskSpinBox() override;
|
||||||
|
|
||||||
#if 1
|
void setButtons( bool );
|
||||||
/*
|
bool hasButtons() const;
|
||||||
-1: decrease
|
|
||||||
0: none
|
void setWrapping( bool );
|
||||||
1: increment
|
bool isWrapping() const;
|
||||||
*/
|
|
||||||
int pressedButton() const;
|
void setTracking( bool );
|
||||||
int hoveredButton() const;
|
bool isTracking() const;
|
||||||
#endif
|
|
||||||
|
void setAccelerating( bool );
|
||||||
|
bool isAccelerating() const;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void trackingChanged( bool );
|
||||||
|
void wrappingChanged( bool );
|
||||||
|
void acceleratingChanged( bool );
|
||||||
|
void buttonsChanged( bool );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void hoverEnterEvent( QHoverEvent* event ) override;
|
void timerEvent( QTimerEvent* ) override;
|
||||||
void hoverLeaveEvent( QHoverEvent* event ) override;
|
|
||||||
void hoverMoveEvent( QHoverEvent* event ) override;
|
|
||||||
|
|
||||||
void mouseReleaseEvent( QMouseEvent* event ) override;
|
void mouseReleaseEvent( QMouseEvent* ) override;
|
||||||
void mousePressEvent( QMouseEvent* event ) override;
|
void mousePressEvent( QMouseEvent* ) override;
|
||||||
|
|
||||||
void keyPressEvent( QKeyEvent* event ) override;
|
void keyPressEvent( QKeyEvent* ) override;
|
||||||
void keyReleaseEvent( QKeyEvent* event ) override;
|
void keyReleaseEvent( QKeyEvent* ) override;
|
||||||
|
|
||||||
class PrivateData;
|
class PrivateData;
|
||||||
std::unique_ptr< PrivateData > m_data;
|
std::unique_ptr< PrivateData > m_data;
|
||||||
|
|
|
@ -8,70 +8,10 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
inline QPointF cursorPosSkinHint( const QskSpinBox& spinbox )
|
|
||||||
{
|
|
||||||
const auto aspect = QskSpinBox::Panel | QskAspect::Metric | QskAspect::Position;
|
|
||||||
return spinbox.effectiveSkinHint( aspect ).toPointF();
|
|
||||||
}
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
Dec = 0,
|
|
||||||
Txt = 1,
|
|
||||||
Inc = 2,
|
|
||||||
Count
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
QskSpinBoxSkinlet::QskSpinBoxSkinlet( QskSkin* )
|
QskSpinBoxSkinlet::QskSpinBoxSkinlet( QskSkin* )
|
||||||
{
|
{
|
||||||
setNodeRoles( { IncrementPanel, DecrementPanel, TextPanel,
|
setNodeRoles( { UpPanel, DownPanel, TextPanel,
|
||||||
IncrementIndicator, DecrementIndicator, Text } );
|
UpIndicator, DownIndicator, Text } );
|
||||||
}
|
|
||||||
|
|
||||||
int QskSpinBoxSkinlet::sampleCount(
|
|
||||||
const QskSkinnable*, QskAspect::Subcontrol ) const
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
QRectF QskSpinBoxSkinlet::sampleRect( const QskSkinnable* skinnable, const QRectF& rect,
|
|
||||||
QskAspect::Subcontrol subControl, int index ) const
|
|
||||||
{
|
|
||||||
if ( index == Dec || index == Inc || index == Txt )
|
|
||||||
{
|
|
||||||
return subControlRect( skinnable, rect, subControl );
|
|
||||||
}
|
|
||||||
|
|
||||||
return Inherited::sampleRect( skinnable, rect, subControl, index );
|
|
||||||
}
|
|
||||||
|
|
||||||
QskAspect::States QskSpinBoxSkinlet::sampleStates(
|
|
||||||
const QskSkinnable* const skinnable, QskAspect::Subcontrol subControl, int index ) const
|
|
||||||
{
|
|
||||||
using S = QskSpinBox;
|
|
||||||
|
|
||||||
auto states = Inherited::sampleStates( skinnable, subControl, index );
|
|
||||||
|
|
||||||
if ( subControl == S::DecrementPanel || subControl == S::IncrementPanel ||
|
|
||||||
subControl == S::TextPanel )
|
|
||||||
{
|
|
||||||
const auto* const spinbox = static_cast< const S* >( skinnable );
|
|
||||||
const auto cursorPos = cursorPosSkinHint( *spinbox );
|
|
||||||
const QPointF cursorPosAbs{ qAbs( cursorPos.x() ), qAbs( cursorPos.y() ) };
|
|
||||||
const auto subControlRect = spinbox->subControlRect( subControl );
|
|
||||||
|
|
||||||
const auto contain = !cursorPosAbs.isNull() && subControlRect.contains( cursorPosAbs );
|
|
||||||
const auto pressed = contain && ( cursorPos.x() < 0 || cursorPos.y() < 0 );
|
|
||||||
const auto hovered = contain && !pressed;
|
|
||||||
|
|
||||||
states.setFlag( QskControl::Hovered, hovered );
|
|
||||||
states.setFlag( QskSpinBox::Pressed, pressed );
|
|
||||||
}
|
|
||||||
|
|
||||||
return states;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QskSpinBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
|
QSizeF QskSpinBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||||
|
@ -80,16 +20,16 @@ QSizeF QskSpinBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||||
if ( which != Qt::PreferredSize )
|
if ( which != Qt::PreferredSize )
|
||||||
return QSizeF();
|
return QSizeF();
|
||||||
|
|
||||||
using S = QskSpinBox;
|
using Q = QskSpinBox;
|
||||||
|
|
||||||
const auto spinbox = static_cast< const QskSpinBox* >( skinnable );
|
const auto spinbox = static_cast< const QskSpinBox* >( skinnable );
|
||||||
|
|
||||||
const auto layout = spinbox->alignmentHint( S::Panel );
|
const auto layout = spinbox->alignmentHint( Q::Panel );
|
||||||
const auto spacing = spinbox->spacingHint( S::Panel );
|
const auto spacing = spinbox->spacingHint( Q::Panel );
|
||||||
|
|
||||||
const auto strutInc = spinbox->strutSizeHint( S::IncrementPanel );
|
const auto strutInc = spinbox->strutSizeHint( Q::UpPanel );
|
||||||
const auto strutDec = spinbox->strutSizeHint( S::DecrementPanel );
|
const auto strutDec = spinbox->strutSizeHint( Q::DownPanel );
|
||||||
const auto strutTxt = spinbox->strutSizeHint( S::TextPanel );
|
const auto strutTxt = spinbox->strutSizeHint( Q::TextPanel );
|
||||||
|
|
||||||
if ( layout == Qt::AlignTop || layout == Qt::AlignBottom || layout == Qt::AlignVCenter )
|
if ( layout == Qt::AlignTop || layout == Qt::AlignBottom || layout == Qt::AlignVCenter )
|
||||||
{
|
{
|
||||||
|
@ -118,7 +58,7 @@ QSizeF QskSpinBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( layout == ( Qt::AlignTop | Qt::AlignHCenter ) ||
|
if ( layout == ( Qt::AlignTop | Qt::AlignHCenter ) ||
|
||||||
layout == ( Qt::AlignTop | Qt::AlignHCenter ) )
|
layout == ( Qt::AlignBottom | Qt::AlignHCenter ) )
|
||||||
{
|
{
|
||||||
const auto w = qMax( strutTxt.width(), strutInc.width() + strutDec.width() );
|
const auto w = qMax( strutTxt.width(), strutInc.width() + strutDec.width() );
|
||||||
const auto h = strutTxt.height() + qMax( strutInc.height(), strutDec.height() );
|
const auto h = strutTxt.height() + qMax( strutInc.height(), strutDec.height() );
|
||||||
|
@ -134,11 +74,11 @@ QRectF QskSpinBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
|
||||||
{
|
{
|
||||||
using Q = QskSpinBox;
|
using Q = QskSpinBox;
|
||||||
|
|
||||||
if ( subControl == Q::DecrementIndicator )
|
if ( subControl == Q::DownIndicator )
|
||||||
return skinnable->subControlContentsRect( contentsRect, Q::DecrementPanel );
|
return skinnable->subControlContentsRect( contentsRect, Q::DownPanel );
|
||||||
|
|
||||||
if ( subControl == Q::IncrementIndicator )
|
if ( subControl == Q::UpIndicator )
|
||||||
return skinnable->subControlContentsRect( contentsRect, Q::IncrementPanel );
|
return skinnable->subControlContentsRect( contentsRect, Q::UpPanel );
|
||||||
|
|
||||||
if ( subControl == Q::Text )
|
if ( subControl == Q::Text )
|
||||||
return skinnable->subControlContentsRect( contentsRect, Q::TextPanel );
|
return skinnable->subControlContentsRect( contentsRect, Q::TextPanel );
|
||||||
|
@ -148,10 +88,18 @@ QRectF QskSpinBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
|
||||||
const auto layout = spinbox->alignmentHint( Q::Panel );
|
const auto layout = spinbox->alignmentHint( Q::Panel );
|
||||||
const auto spacing = spinbox->spacingHint( Q::Panel );
|
const auto spacing = spinbox->spacingHint( Q::Panel );
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Dec = 0,
|
||||||
|
Txt = 1,
|
||||||
|
Inc = 2,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
std::array< QRectF, Count > rects = {
|
std::array< QRectF, Count > rects = {
|
||||||
QRectF{ QPointF(), spinbox->strutSizeHint( Q::DecrementPanel ) },
|
QRectF{ QPointF(), spinbox->strutSizeHint( Q::DownPanel ) },
|
||||||
QRectF{ QPointF(), spinbox->strutSizeHint( Q::TextPanel ) },
|
QRectF{ QPointF(), spinbox->strutSizeHint( Q::TextPanel ) },
|
||||||
QRectF{ QPointF(), spinbox->strutSizeHint( Q::IncrementPanel ) },
|
QRectF{ QPointF(), spinbox->strutSizeHint( Q::UpPanel ) },
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto center = contentsRect.center();
|
const auto center = contentsRect.center();
|
||||||
|
@ -238,13 +186,13 @@ QRectF QskSpinBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
|
||||||
{ center.x() + spacing * 0.5, rects[ Txt ].top() - spacing - rects[ Inc ].height() } );
|
{ center.x() + spacing * 0.5, rects[ Txt ].top() - spacing - rects[ Inc ].height() } );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( subControl == Q::DecrementPanel )
|
if ( subControl == Q::DownPanel )
|
||||||
return rects[ Dec ];
|
return rects[ Dec ];
|
||||||
|
|
||||||
if ( subControl == Q::TextPanel )
|
if ( subControl == Q::TextPanel )
|
||||||
return rects[ Txt ];
|
return rects[ Txt ];
|
||||||
|
|
||||||
if ( subControl == Q::IncrementPanel )
|
if ( subControl == Q::UpPanel )
|
||||||
return rects[ Inc ];
|
return rects[ Inc ];
|
||||||
|
|
||||||
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
||||||
|
@ -257,26 +205,26 @@ QSGNode* QskSpinBoxSkinlet::updateSubNode(
|
||||||
|
|
||||||
switch( nodeRole )
|
switch( nodeRole )
|
||||||
{
|
{
|
||||||
case IncrementPanel:
|
case UpPanel:
|
||||||
return updateSeriesNode( skinnable, Q::IncrementPanel, node );
|
return updateBoxNode( skinnable, node, Q::UpPanel );
|
||||||
|
|
||||||
case DecrementPanel:
|
case DownPanel:
|
||||||
return updateSeriesNode( skinnable, Q::DecrementPanel, node );
|
return updateBoxNode( skinnable, node, Q::DownPanel );
|
||||||
|
|
||||||
case IncrementIndicator:
|
case UpIndicator:
|
||||||
{
|
{
|
||||||
return updateTextNode( skinnable, node,
|
return updateTextNode( skinnable, node,
|
||||||
QStringLiteral( "+" ), Q::IncrementIndicator );
|
QStringLiteral( "+" ), Q::UpIndicator );
|
||||||
}
|
}
|
||||||
|
|
||||||
case DecrementIndicator:
|
case DownIndicator:
|
||||||
{
|
{
|
||||||
return updateTextNode( skinnable, node,
|
return updateTextNode( skinnable, node,
|
||||||
QStringLiteral( "-" ), Q::DecrementIndicator );
|
QStringLiteral( "-" ), Q::DownIndicator );
|
||||||
}
|
}
|
||||||
|
|
||||||
case TextPanel:
|
case TextPanel:
|
||||||
return updateSeriesNode( skinnable, Q::TextPanel, node );
|
return updateBoxNode( skinnable, node, Q::TextPanel );
|
||||||
|
|
||||||
case Text:
|
case Text:
|
||||||
{
|
{
|
||||||
|
@ -289,19 +237,3 @@ QSGNode* QskSpinBoxSkinlet::updateSubNode(
|
||||||
|
|
||||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGNode* QskSpinBoxSkinlet::updateSampleNode( const QskSkinnable* skinnable,
|
|
||||||
QskAspect::Subcontrol subControl, const int index, QSGNode* const node ) const
|
|
||||||
{
|
|
||||||
using Q = QskSpinBox;
|
|
||||||
const auto* const spinbox = static_cast< const QskSpinBox* >( skinnable );
|
|
||||||
|
|
||||||
if ( subControl == Q::DecrementPanel || subControl == Q::IncrementPanel ||
|
|
||||||
subControl == Q::TextPanel )
|
|
||||||
{
|
|
||||||
const auto rect = sampleRect( spinbox, spinbox->contentsRect(), subControl, index );
|
|
||||||
return updateBoxNode( skinnable, node, rect, subControl );
|
|
||||||
}
|
|
||||||
|
|
||||||
return Inherited::updateSampleNode( skinnable, subControl, index, node );
|
|
||||||
}
|
|
||||||
|
|
|
@ -18,14 +18,15 @@ class QSK_EXPORT QskSpinBoxSkinlet : public QskSkinlet
|
||||||
|
|
||||||
enum NodeRole
|
enum NodeRole
|
||||||
{
|
{
|
||||||
IncrementPanel,
|
|
||||||
DecrementPanel,
|
|
||||||
TextPanel,
|
TextPanel,
|
||||||
|
|
||||||
IncrementIndicator,
|
|
||||||
DecrementIndicator,
|
|
||||||
Text,
|
Text,
|
||||||
|
|
||||||
|
UpPanel,
|
||||||
|
UpIndicator,
|
||||||
|
|
||||||
|
DownPanel,
|
||||||
|
DownIndicator,
|
||||||
|
|
||||||
RoleCount
|
RoleCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,21 +36,9 @@ class QSK_EXPORT QskSpinBoxSkinlet : public QskSkinlet
|
||||||
QSizeF sizeHint( const QskSkinnable* skinnable,
|
QSizeF sizeHint( const QskSkinnable* skinnable,
|
||||||
Qt::SizeHint, const QSizeF& ) const override;
|
Qt::SizeHint, const QSizeF& ) const override;
|
||||||
|
|
||||||
int sampleCount(
|
|
||||||
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) const override;
|
|
||||||
|
|
||||||
QRectF sampleRect( const QskSkinnable* skinnable, const QRectF& rect,
|
|
||||||
QskAspect::Subcontrol subControl, int index ) const override;
|
|
||||||
|
|
||||||
QskAspect::States sampleStates( const QskSkinnable*,
|
|
||||||
QskAspect::Subcontrol, int index ) const override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QSGNode* updateSubNode(
|
QSGNode* updateSubNode(
|
||||||
const QskSkinnable* skinnable, quint8 role, QSGNode* node ) const override;
|
const QskSkinnable* skinnable, quint8 role, QSGNode* node ) const override;
|
||||||
|
|
||||||
QSGNode* updateSampleNode( const QskSkinnable*, QskAspect::Subcontrol,
|
|
||||||
int index, QSGNode* node ) const override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue