slider ticks - not only for M3
This commit is contained in:
parent
d04c030924
commit
9a5dd886ed
@ -927,15 +927,15 @@ void Editor::setupSlider()
|
||||
setBoxShape( Q::Groove, 100, Qt::RelativeSize );
|
||||
setBoxShape( Q::Fill, 100, Qt::RelativeSize );
|
||||
|
||||
setStrutSize( Q::Ticks, { 4_dp, 4_dp } );
|
||||
setBoxShape( Q::Ticks, 100, Qt::RelativeSize );
|
||||
setStrutSize( Q::Tick, { 4_dp, 4_dp } );
|
||||
setBoxShape( Q::Tick, 100, Qt::RelativeSize );
|
||||
|
||||
setGradient( Q::Ticks, m_pal.primary );
|
||||
setGradient( Q::Ticks | Q::Disabled, m_pal.onSurface );
|
||||
setGradient( Q::Tick, m_pal.primary );
|
||||
setGradient( Q::Tick | Q::Disabled, m_pal.onSurface );
|
||||
|
||||
setGradient( Q::Ticks | SK::Filled, m_pal.secondaryContainer,
|
||||
setGradient( Q::Tick | SK::Filled, m_pal.secondaryContainer,
|
||||
{ QskStateCombination::CombinationNoState, Q::Focused | Q::Pressed } );
|
||||
setGradient( Q::Ticks | SK::Filled | Q::Disabled, m_pal.inverseOnSurface );
|
||||
setGradient( Q::Tick | SK::Filled | Q::Disabled, m_pal.inverseOnSurface );
|
||||
|
||||
for ( const auto variation : { A::Horizontal, A::Vertical } )
|
||||
{
|
||||
|
@ -16,31 +16,9 @@ QSK_SYSTEM_STATE( QskMaterial3SliderSkinlet, Filled, QskAspect::FirstUserState >
|
||||
|
||||
using Q = QskSlider;
|
||||
|
||||
static inline bool qskHasOrigin( const QskSlider* )
|
||||
static inline bool qskHasBoundaryTicks( const QskSlider* slider )
|
||||
{
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
static inline qreal qskTickValue( const QskSlider* slider, int index )
|
||||
{
|
||||
if( slider->isSnapping() && slider->stepSize() )
|
||||
return slider->minimum() + index * slider->stepSize();
|
||||
|
||||
if ( qskHasOrigin( slider ) )
|
||||
{
|
||||
switch( index )
|
||||
{
|
||||
case 0:
|
||||
return slider->minimum();
|
||||
|
||||
#if 0
|
||||
case 1:
|
||||
return slider->origin();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return slider->maximum();
|
||||
return ( slider->graduationPolicy() == Qsk::Maybe ) && !slider->isSnapping();
|
||||
}
|
||||
|
||||
QskMaterial3SliderSkinlet::QskMaterial3SliderSkinlet( QskSkin* skin )
|
||||
@ -82,7 +60,7 @@ QSGNode* QskMaterial3SliderSkinlet::updateSubNode(
|
||||
case GrooveRole:
|
||||
case FillRole:
|
||||
{
|
||||
auto clippedNode = QskSGNode::findChildNode( node, nodeRole );
|
||||
auto clippedNode = QskSGNode::findChildNode( node, nodeRole );
|
||||
clippedNode = Inherited::updateSubNode( skinnable, nodeRole, clippedNode );
|
||||
|
||||
if ( clippedNode )
|
||||
@ -102,11 +80,6 @@ QSGNode* QskMaterial3SliderSkinlet::updateSubNode(
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case TicksRole:
|
||||
{
|
||||
return updateSeriesNode( skinnable, Q::Ticks, node );
|
||||
}
|
||||
}
|
||||
|
||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||
@ -115,48 +88,50 @@ QSGNode* QskMaterial3SliderSkinlet::updateSubNode(
|
||||
int QskMaterial3SliderSkinlet::sampleCount( const QskSkinnable* skinnable,
|
||||
QskAspect::Subcontrol subControl ) const
|
||||
{
|
||||
if ( subControl == Q::Ticks )
|
||||
if ( subControl == Q::Tick )
|
||||
{
|
||||
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||
|
||||
if( slider->isSnapping() && slider->stepSize() )
|
||||
return qCeil( slider->boundaryLength() / slider->stepSize() ) + 1;
|
||||
if ( qskHasBoundaryTicks( slider ) )
|
||||
{
|
||||
const bool hasOrigin = false;
|
||||
|
||||
// min/origin/max or max
|
||||
return qskHasOrigin( slider ) ? 3 : 1;
|
||||
// min/origin/max or max
|
||||
return hasOrigin ? 3 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
return Inherited::sampleCount( skinnable, subControl );
|
||||
}
|
||||
|
||||
QRectF QskMaterial3SliderSkinlet::sampleRect(
|
||||
const QskSkinnable* skinnable, const QRectF& contentsRect,
|
||||
QVariant QskMaterial3SliderSkinlet::sampleAt( const QskSkinnable* skinnable,
|
||||
QskAspect::Subcontrol subControl, int index ) const
|
||||
{
|
||||
if ( subControl != Q::Ticks )
|
||||
return Inherited::sampleRect( skinnable, contentsRect, subControl, index );
|
||||
|
||||
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||
|
||||
const auto tickPos = slider->valueAsRatio( qskTickValue( slider, index ) );
|
||||
|
||||
const auto size = skinnable->strutSizeHint( Q::Ticks );
|
||||
const auto r = subControlRect( skinnable, contentsRect, Q::Scale );
|
||||
|
||||
qreal x, y;
|
||||
|
||||
if( slider->orientation() == Qt::Horizontal )
|
||||
if ( subControl == Q::Tick )
|
||||
{
|
||||
x = tickPos * r.width() - 0.5 * size.width();
|
||||
y = 0.5 * ( r.height() - size.height() );
|
||||
}
|
||||
else
|
||||
{
|
||||
y = r.height() - ( tickPos * r.height() ) - 0.5 * size.height();
|
||||
x = 0.5 * ( r.width() - size.width() );
|
||||
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||
|
||||
if ( qskHasBoundaryTicks( slider ) )
|
||||
{
|
||||
switch( index )
|
||||
{
|
||||
case 1:
|
||||
return slider->minimum();
|
||||
|
||||
#if 0
|
||||
case 2:
|
||||
return slider->origin();
|
||||
#endif
|
||||
|
||||
default:
|
||||
return slider->maximum();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
return QRectF( r.x() + x, r.y() + y, size.width(), size.height() );
|
||||
return Inherited::sampleAt( skinnable, subControl, index );
|
||||
}
|
||||
|
||||
QskAspect::States QskMaterial3SliderSkinlet::sampleStates(
|
||||
@ -164,28 +139,19 @@ QskAspect::States QskMaterial3SliderSkinlet::sampleStates(
|
||||
{
|
||||
auto states = Inherited::sampleStates( skinnable, subControl, index );
|
||||
|
||||
if ( subControl == Q::Ticks )
|
||||
if ( subControl == Q::Tick )
|
||||
{
|
||||
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||
if ( qskTickValue( slider, index ) <= slider->value() )
|
||||
states |= QskMaterial3SliderSkinlet::Filled;
|
||||
const auto tickValue = sampleAt( skinnable, subControl, index );
|
||||
if ( tickValue.canConvert< qreal >() )
|
||||
{
|
||||
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||
|
||||
if ( tickValue.value< qreal >() <= slider->value() )
|
||||
states |= QskMaterial3SliderSkinlet::Filled;
|
||||
}
|
||||
}
|
||||
|
||||
return states;
|
||||
}
|
||||
|
||||
QSGNode* QskMaterial3SliderSkinlet::updateSampleNode( const QskSkinnable* skinnable,
|
||||
QskAspect::Subcontrol subControl, int index, QSGNode* node ) const
|
||||
{
|
||||
if ( subControl == Q::Ticks )
|
||||
{
|
||||
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||
const auto rect = sampleRect( slider, slider->contentsRect(), subControl, index );
|
||||
|
||||
return updateBoxNode( skinnable, node, rect, subControl );
|
||||
}
|
||||
|
||||
return Inherited::updateSampleNode( skinnable, subControl, index, node );
|
||||
}
|
||||
|
||||
#include "moc_QskMaterial3SliderSkinlet.cpp"
|
||||
|
@ -24,8 +24,8 @@ class QskMaterial3SliderSkinlet : QskSliderSkinlet
|
||||
|
||||
int sampleCount( const QskSkinnable*, QskAspect::Subcontrol ) const override;
|
||||
|
||||
QRectF sampleRect( const QskSkinnable*,
|
||||
const QRectF&, QskAspect::Subcontrol, int index ) const override;
|
||||
QVariant sampleAt( const QskSkinnable*,
|
||||
QskAspect::Subcontrol, int index ) const override;
|
||||
|
||||
QskAspect::States sampleStates( const QskSkinnable*,
|
||||
QskAspect::Subcontrol, int ) const override;
|
||||
@ -33,9 +33,6 @@ class QskMaterial3SliderSkinlet : QskSliderSkinlet
|
||||
protected:
|
||||
QSGNode* updateSubNode( const QskSkinnable*,
|
||||
quint8 nodeRole, QSGNode* ) const override;
|
||||
|
||||
QSGNode* updateSampleNode( const QskSkinnable*,
|
||||
QskAspect::Subcontrol, int index, QSGNode* ) const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -13,6 +13,14 @@ namespace Qsk
|
||||
{
|
||||
Q_NAMESPACE_EXPORT( QSK_EXPORT )
|
||||
|
||||
enum Policy
|
||||
{
|
||||
Maybe,
|
||||
Always,
|
||||
Never
|
||||
};
|
||||
Q_ENUM_NS( Policy )
|
||||
|
||||
enum Direction
|
||||
{
|
||||
LeftToRight,
|
||||
|
@ -9,15 +9,42 @@
|
||||
#include "QskIntervalF.h"
|
||||
#include "QskEvent.h"
|
||||
|
||||
#include <qmath.h>
|
||||
|
||||
QSK_SUBCONTROL( QskSlider, Panel )
|
||||
QSK_SUBCONTROL( QskSlider, Groove )
|
||||
QSK_SUBCONTROL( QskSlider, Fill )
|
||||
QSK_SUBCONTROL( QskSlider, Scale )
|
||||
QSK_SUBCONTROL( QskSlider, Ticks )
|
||||
QSK_SUBCONTROL( QskSlider, Tick )
|
||||
QSK_SUBCONTROL( QskSlider, Handle )
|
||||
|
||||
QSK_SYSTEM_STATE( QskSlider, Pressed, QskAspect::FirstSystemState << 2 )
|
||||
|
||||
static inline constexpr QskAspect qskAspectGraduationPolicy()
|
||||
{
|
||||
return QskSlider::Tick | QskAspect::Option;
|
||||
}
|
||||
|
||||
static inline bool qskHasGraduation( const QskSlider* slider )
|
||||
{
|
||||
if ( slider->stepSize() )
|
||||
{
|
||||
switch( slider->graduationPolicy() )
|
||||
{
|
||||
case Qsk::Always:
|
||||
return true;
|
||||
|
||||
case Qsk::Maybe:
|
||||
return slider->isSnapping();
|
||||
|
||||
case Qsk::Never:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
class QskSlider::PrivateData
|
||||
{
|
||||
public:
|
||||
@ -90,6 +117,42 @@ QskAspect::Variation QskSlider::effectiveVariation() const
|
||||
return static_cast< QskAspect::Variation >( m_data->orientation );
|
||||
}
|
||||
|
||||
void QskSlider::setGraduationPolicy( Qsk::Policy policy )
|
||||
{
|
||||
if ( setFlagHint( qskAspectGraduationPolicy(), policy ) )
|
||||
Q_EMIT graduationPolicyChanged( graduationPolicy() );
|
||||
}
|
||||
|
||||
void QskSlider::resetGraduationPolicy()
|
||||
{
|
||||
if ( resetSkinHint( qskAspectGraduationPolicy() ) )
|
||||
Q_EMIT graduationPolicyChanged( graduationPolicy() );
|
||||
}
|
||||
|
||||
Qsk::Policy QskSlider::graduationPolicy() const
|
||||
{
|
||||
return flagHint< Qsk::Policy >( qskAspectGraduationPolicy(), Qsk::Maybe );
|
||||
}
|
||||
|
||||
QVector< qreal > QskSlider::visualGraduation() const
|
||||
{
|
||||
QVector< qreal > graduation;
|
||||
|
||||
if ( qskHasGraduation( this ) )
|
||||
{
|
||||
const auto n = qCeil( boundaryLength() / stepSize() ) + 1;
|
||||
|
||||
graduation.reserve( n );
|
||||
|
||||
for ( int i = 0; i < n - 1; i++ )
|
||||
graduation += minimum() + i * stepSize();
|
||||
|
||||
graduation += maximum();
|
||||
}
|
||||
|
||||
return graduation;
|
||||
}
|
||||
|
||||
void QskSlider::setTracking( bool on )
|
||||
{
|
||||
if ( on != m_data->tracking )
|
||||
|
@ -7,6 +7,9 @@
|
||||
#define QSK_SLIDER_H
|
||||
|
||||
#include "QskBoundedValueInput.h"
|
||||
#include "QskNamespace.h"
|
||||
|
||||
#include <qvector.h>
|
||||
|
||||
class QSK_EXPORT QskSlider : public QskBoundedValueInput
|
||||
{
|
||||
@ -14,6 +17,10 @@ class QSK_EXPORT QskSlider : public QskBoundedValueInput
|
||||
|
||||
Q_PROPERTY( bool isPressed READ isPressed NOTIFY pressedChanged )
|
||||
|
||||
Q_PROPERTY( Qsk::Policy graduationPolicy READ graduationPolicy
|
||||
WRITE setGraduationPolicy RESET resetGraduationPolicy
|
||||
NOTIFY graduationPolicyChanged )
|
||||
|
||||
Q_PROPERTY( Qt::Orientation orientation READ orientation
|
||||
WRITE setOrientation NOTIFY orientationChanged )
|
||||
|
||||
@ -25,7 +32,7 @@ class QSK_EXPORT QskSlider : public QskBoundedValueInput
|
||||
using Inherited = QskBoundedValueInput;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Panel, Groove, Fill, Scale, Ticks, Handle )
|
||||
QSK_SUBCONTROLS( Panel, Groove, Fill, Scale, Tick, Handle )
|
||||
QSK_STATES( Pressed )
|
||||
|
||||
explicit QskSlider( QQuickItem* parent = nullptr );
|
||||
@ -38,6 +45,12 @@ class QSK_EXPORT QskSlider : public QskBoundedValueInput
|
||||
void setOrientation( Qt::Orientation );
|
||||
Qt::Orientation orientation() const;
|
||||
|
||||
void setGraduationPolicy( Qsk::Policy );
|
||||
void resetGraduationPolicy();
|
||||
Qsk::Policy graduationPolicy() const;
|
||||
|
||||
virtual QVector< qreal > visualGraduation() const;
|
||||
|
||||
void setTracking( bool );
|
||||
bool isTracking() const;
|
||||
|
||||
@ -49,6 +62,7 @@ class QSK_EXPORT QskSlider : public QskBoundedValueInput
|
||||
void pressedChanged( bool );
|
||||
void orientationChanged( Qt::Orientation );
|
||||
void trackingChanged( bool );
|
||||
void graduationPolicyChanged( Qsk::Policy );
|
||||
|
||||
protected:
|
||||
void mousePressEvent( QMouseEvent* ) override;
|
||||
|
@ -89,11 +89,65 @@ QSGNode* QskSliderSkinlet::updateSubNode(
|
||||
|
||||
case HandleRole:
|
||||
return updateBoxNode( slider, node, Q::Handle );
|
||||
|
||||
case TicksRole:
|
||||
return updateSeriesNode( slider, Q::Tick, node );
|
||||
}
|
||||
|
||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||
}
|
||||
|
||||
int QskSliderSkinlet::sampleCount( const QskSkinnable* skinnable,
|
||||
QskAspect::Subcontrol subControl ) const
|
||||
{
|
||||
if ( subControl == Q::Tick )
|
||||
{
|
||||
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||
return slider->visualGraduation().count();
|
||||
}
|
||||
|
||||
return Inherited::sampleCount( skinnable, subControl );
|
||||
}
|
||||
|
||||
QVariant QskSliderSkinlet::sampleAt( const QskSkinnable* skinnable,
|
||||
QskAspect::Subcontrol subControl, int index ) const
|
||||
{
|
||||
if ( subControl == Q::Tick )
|
||||
{
|
||||
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||
return slider->visualGraduation().value( index );
|
||||
}
|
||||
|
||||
return Inherited::sampleAt( skinnable, subControl, index );
|
||||
}
|
||||
|
||||
QRectF QskSliderSkinlet::sampleRect(
|
||||
const QskSkinnable* skinnable, const QRectF& contentsRect,
|
||||
QskAspect::Subcontrol subControl, int index ) const
|
||||
{
|
||||
if ( subControl == Q::Tick )
|
||||
{
|
||||
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||
return tickRect( slider, contentsRect, index );
|
||||
}
|
||||
|
||||
return Inherited::sampleRect( skinnable, contentsRect, subControl, index );
|
||||
}
|
||||
|
||||
QSGNode* QskSliderSkinlet::updateSampleNode( const QskSkinnable* skinnable,
|
||||
QskAspect::Subcontrol subControl, int index, QSGNode* node ) const
|
||||
{
|
||||
if ( subControl == Q::Tick )
|
||||
{
|
||||
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||
const auto rect = sampleRect( slider, slider->contentsRect(), subControl, index );
|
||||
|
||||
return updateBoxNode( skinnable, node, rect, subControl );
|
||||
}
|
||||
|
||||
return Inherited::updateSampleNode( skinnable, subControl, index, node );
|
||||
}
|
||||
|
||||
QRectF QskSliderSkinlet::panelRect(
|
||||
const QskSlider* slider, const QRectF& contentsRect ) const
|
||||
{
|
||||
@ -166,6 +220,34 @@ QRectF QskSliderSkinlet::handleRect(
|
||||
return handleRect;
|
||||
}
|
||||
|
||||
QRectF QskSliderSkinlet::tickRect( const QskSlider* slider,
|
||||
const QRectF& contentsRect, int index ) const
|
||||
{
|
||||
const auto tickValue = sampleAt( slider, Q::Tick, index );
|
||||
if ( !tickValue.canConvert< qreal >() )
|
||||
return QRectF();
|
||||
|
||||
const auto tickPos = slider->valueAsRatio( tickValue.value< qreal >() );
|
||||
|
||||
const auto size = slider->strutSizeHint( Q::Tick );
|
||||
const auto r = subControlRect( slider, contentsRect, Q::Scale );
|
||||
|
||||
qreal x, y;
|
||||
|
||||
if( slider->orientation() == Qt::Horizontal )
|
||||
{
|
||||
x = tickPos * r.width() - 0.5 * size.width();
|
||||
y = 0.5 * ( r.height() - size.height() );
|
||||
}
|
||||
else
|
||||
{
|
||||
y = r.height() - ( tickPos * r.height() ) - 0.5 * size.height();
|
||||
x = 0.5 * ( r.width() - size.width() );
|
||||
}
|
||||
|
||||
return QRectF( r.x() + x, r.y() + y, size.width(), size.height() );
|
||||
}
|
||||
|
||||
QSizeF QskSliderSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||
Qt::SizeHint which, const QSizeF& ) const
|
||||
{
|
||||
|
@ -37,14 +37,26 @@ class QSK_EXPORT QskSliderSkinlet : public QskSkinlet
|
||||
QSizeF sizeHint( const QskSkinnable*,
|
||||
Qt::SizeHint, const QSizeF& ) const override;
|
||||
|
||||
int sampleCount( const QskSkinnable*, QskAspect::Subcontrol ) const override;
|
||||
|
||||
QRectF sampleRect( const QskSkinnable*,
|
||||
const QRectF&, QskAspect::Subcontrol, int index ) const override;
|
||||
|
||||
QVariant sampleAt( const QskSkinnable*,
|
||||
QskAspect::Subcontrol, int index ) const override;
|
||||
|
||||
protected:
|
||||
QSGNode* updateSubNode( const QskSkinnable*,
|
||||
quint8 nodeRole, QSGNode* ) const override;
|
||||
|
||||
QSGNode* updateSampleNode( const QskSkinnable*,
|
||||
QskAspect::Subcontrol, int index, QSGNode* ) const override;
|
||||
|
||||
private:
|
||||
QRectF panelRect( const QskSlider*, const QRectF& ) const;
|
||||
QRectF fillRect( const QskSlider*, const QRectF& ) const;
|
||||
QRectF handleRect( const QskSlider*, const QRectF& ) const;
|
||||
QRectF tickRect( const QskSlider*, const QRectF&, int index ) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user