Merge branch 'issues/391-m3-slider' of https://github.com/edelhirsch/qskinny into m3slider
This commit is contained in:
commit
ad7e24faa5
|
@ -839,41 +839,40 @@ void Editor::setupSlider()
|
||||||
using A = QskAspect;
|
using A = QskAspect;
|
||||||
using Q = QskSlider;
|
using Q = QskSlider;
|
||||||
|
|
||||||
const qreal extent = 30_dp;
|
const QSizeF sliderSize( 48_dp, 44_dp );
|
||||||
|
setStrutSize( Q::Panel | A::Horizontal, sliderSize );
|
||||||
|
setStrutSize( Q::Panel | A::Vertical, sliderSize.transposed() );
|
||||||
|
|
||||||
// Panel
|
setBoxShape( Q::Groove | A::Horizontal, { 0, 100, 0, 100, Qt::RelativeSize } );
|
||||||
|
setBoxShape( Q::Groove | A::Vertical, { 100, 100, 0, 0, Qt::RelativeSize } );
|
||||||
setMetric( Q::Panel | A::Size, extent );
|
setMetric( Q::Groove | A::Size, 16_dp );
|
||||||
setBoxShape( Q::Panel, 0 );
|
setMargin( Q::Groove | A::Horizontal, { 6_dp, 0, 0, 0 } );
|
||||||
setBoxBorderMetrics( Q::Panel, 0 );
|
setMargin( Q::Groove | A::Vertical, {0, 0, 0, 6_dp } );
|
||||||
setGradient( Q::Panel, QskGradient() );
|
|
||||||
|
|
||||||
setPadding( Q::Panel | A::Horizontal, QskMargins( 0.5 * extent, 0 ) );
|
|
||||||
setPadding( Q::Panel | A::Vertical, QskMargins( 0, 0.5 * extent ) );
|
|
||||||
|
|
||||||
// Groove, Fill
|
|
||||||
|
|
||||||
for ( auto subControl : { Q::Groove, Q::Fill } )
|
|
||||||
{
|
|
||||||
setPadding( subControl, 0 );
|
|
||||||
|
|
||||||
setBoxShape( subControl, 0 );
|
|
||||||
setBoxBorderMetrics( subControl, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
setMetric( Q::Groove | A::Size, 4_dp );
|
|
||||||
setMetric( Q::Fill | A::Size, 6_dp );
|
|
||||||
|
|
||||||
setGradient( Q::Groove, m_pal.primaryContainer );
|
setGradient( Q::Groove, m_pal.primaryContainer );
|
||||||
setGradient( Q::Groove | Q::Disabled, m_pal.onSurface12 );
|
setGradient( Q::Groove | Q::Disabled, m_pal.onSurface12 );
|
||||||
|
|
||||||
|
setBoxShape( Q::Fill | A::Horizontal, { 100, 0, 100, 0, Qt::RelativeSize } );
|
||||||
|
setBoxShape( Q::Fill | A::Vertical, { 0, 0, 100, 100, Qt::RelativeSize } );
|
||||||
|
setMetric( Q::Fill | A::Size, 16_dp );
|
||||||
|
setMargin( Q::Fill | A::Horizontal, { 0, 0, 6_dp, 0 } );
|
||||||
|
setMargin( Q::Fill | A::Vertical, {0, 6_dp, 0, 0 } );
|
||||||
|
|
||||||
setGradient( Q::Fill, m_pal.primary );
|
setGradient( Q::Fill, m_pal.primary );
|
||||||
setGradient( Q::Fill | Q::Disabled, m_pal.onSurface38 );
|
setGradient( Q::Fill | Q::Disabled, m_pal.onSurface38 );
|
||||||
|
|
||||||
setBoxShape( Q::Handle, 100, Qt::RelativeSize );
|
setBoxShape( Q::Handle, 100, Qt::RelativeSize );
|
||||||
setBoxBorderMetrics( Q::Handle, 0 );
|
setBoxBorderMetrics( Q::Handle, 0 );
|
||||||
|
|
||||||
setStrutSize( Q::Handle, 20_dp, 20_dp );
|
const QSizeF handleSize( 4_dp, 44_dp );
|
||||||
|
const QSizeF handleSizeFocusedPressed( 2_dp, 44_dp );
|
||||||
|
setStrutSize( Q::Handle | A::Horizontal, handleSize );
|
||||||
|
setStrutSize( Q::Handle | A::Horizontal, handleSizeFocusedPressed,
|
||||||
|
{ QskStateCombination::Combination, Q::Focused | Q::Pressed } );
|
||||||
|
|
||||||
|
setStrutSize( Q::Handle | A::Vertical, handleSize.transposed() );
|
||||||
|
setStrutSize( Q::Handle | A::Vertical, handleSizeFocusedPressed.transposed(),
|
||||||
|
{ QskStateCombination::Combination, Q::Focused | Q::Pressed } );
|
||||||
|
|
||||||
setGradient( Q::Handle, m_pal.primary );
|
setGradient( Q::Handle, m_pal.primary );
|
||||||
setGradient( Q::Handle | Q::Pressed, m_pal.primary );
|
setGradient( Q::Handle | Q::Pressed, m_pal.primary );
|
||||||
|
@ -881,13 +880,39 @@ void Editor::setupSlider()
|
||||||
const auto disabledColor = flattenedColor( m_pal.onSurface, m_pal.background, 0.38 );
|
const auto disabledColor = flattenedColor( m_pal.onSurface, m_pal.background, 0.38 );
|
||||||
setGradient( Q::Handle | Q::Disabled, disabledColor );
|
setGradient( Q::Handle | Q::Disabled, disabledColor );
|
||||||
|
|
||||||
setStrutSize( Q::Ripple, 40_dp, 40_dp );
|
for( auto indicator : { Q::GrooveStopIndicators, Q::FillStopIndicators } )
|
||||||
setBoxShape( Q::Ripple, 100, Qt::RelativeSize );
|
{
|
||||||
setGradient( Q::Ripple, Qt::transparent );
|
setStrutSize( indicator, { 4_dp, 4_dp } );
|
||||||
setGradient( Q::Ripple | Q::Hovered, m_pal.primary12 );
|
setBoxShape( indicator, 100, Qt::RelativeSize );
|
||||||
setGradient( Q::Ripple | Q::Pressed, m_pal.primary12 );
|
}
|
||||||
|
|
||||||
// move the handle smoothly, when using keys
|
const auto p = 6_dp;
|
||||||
|
setPadding( Q::GrooveStopIndicators | A::Horizontal, { p, 0, p, 0 } );
|
||||||
|
setPadding( Q::GrooveStopIndicators | A::Vertical, { 0, p, 0, p } );
|
||||||
|
setPadding( Q::FillStopIndicators | A::Horizontal, { p, 0, p, 0 } );
|
||||||
|
setPadding( Q::FillStopIndicators | A::Vertical, { 0, p, 0, p } );
|
||||||
|
|
||||||
|
setGradient( Q::GrooveStopIndicators, m_pal.primary );
|
||||||
|
setGradient( Q::GrooveStopIndicators | Q::Disabled, m_pal.onSurface );
|
||||||
|
setGradient( Q::FillStopIndicators, m_pal.secondaryContainer );
|
||||||
|
setGradient( Q::FillStopIndicators | Q::Disabled, m_pal.inverseOnSurface );
|
||||||
|
|
||||||
|
for( const auto state : { Q::Focused, Q::Pressed } )
|
||||||
|
{
|
||||||
|
setStrutSize( Q::LabelContainer | state, 48_dp, 44_dp,
|
||||||
|
{ QskStateCombination::CombinationNoState, Q::Hovered } );
|
||||||
|
}
|
||||||
|
|
||||||
|
setBoxShape( Q::LabelContainer, 100, Qt::RelativeSize );
|
||||||
|
setGradient( Q::LabelContainer, m_pal.inverseSurface );
|
||||||
|
setMargin( Q::LabelContainer | A::Horizontal, { 0, 0, 0, 4_dp } );
|
||||||
|
setMargin( Q::LabelContainer | A::Vertical, { 4_dp, 0, 0, 0 } );
|
||||||
|
|
||||||
|
setFontRole( Q::LabelText, LabelMedium );
|
||||||
|
setColor( Q::LabelText, m_pal.inverseOnSurface );
|
||||||
|
setAlignment( Q::LabelText, Qt::AlignCenter );
|
||||||
|
|
||||||
|
// move the handle smoothly when using keys
|
||||||
setAnimation( Q::Handle | A::Metric | A::Position, 2 * qskDuration );
|
setAnimation( Q::Handle | A::Metric | A::Position, 2 * qskDuration );
|
||||||
setAnimation( Q::Handle | A::Metric | A::Position | Q::Pressed, 0 );
|
setAnimation( Q::Handle | A::Metric | A::Position | Q::Pressed, 0 );
|
||||||
}
|
}
|
||||||
|
@ -1314,6 +1339,7 @@ QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme,
|
||||||
onPrimary = color.toned( 100 ).rgb();
|
onPrimary = color.toned( 100 ).rgb();
|
||||||
primaryContainer = color.toned( 90 ).rgb();
|
primaryContainer = color.toned( 90 ).rgb();
|
||||||
onPrimaryContainer = color.toned( 10 ).rgb();
|
onPrimaryContainer = color.toned( 10 ).rgb();
|
||||||
|
inversePrimary = color.toned( 80 ).rgb();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1350,6 +1376,9 @@ QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme,
|
||||||
onBackground = color.toned( 10 ).rgb();
|
onBackground = color.toned( 10 ).rgb();
|
||||||
surface = color.toned( 99 ).rgb();
|
surface = color.toned( 99 ).rgb();
|
||||||
onSurface = color.toned( 10 ).rgb();
|
onSurface = color.toned( 10 ).rgb();
|
||||||
|
inverseSurface = color.toned( 20 ).rgb();
|
||||||
|
inverseOnSurface = color.toned( 95 ).rgb();
|
||||||
|
scrim = color.toned( 0 ).rgb();
|
||||||
shadow = color.toned( 0 ).rgb();
|
shadow = color.toned( 0 ).rgb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1373,6 +1402,7 @@ QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme,
|
||||||
onPrimary = color.toned( 20 ).rgb();
|
onPrimary = color.toned( 20 ).rgb();
|
||||||
primaryContainer = color.toned( 30 ).rgb();
|
primaryContainer = color.toned( 30 ).rgb();
|
||||||
onPrimaryContainer = color.toned( 90 ).rgb();
|
onPrimaryContainer = color.toned( 90 ).rgb();
|
||||||
|
inversePrimary = color.toned( 40 ).rgb();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1409,6 +1439,9 @@ QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme,
|
||||||
onBackground = color.toned( 90 ).rgb();
|
onBackground = color.toned( 90 ).rgb();
|
||||||
surface = color.toned( 10 ).rgb();
|
surface = color.toned( 10 ).rgb();
|
||||||
onSurface = color.toned( 80 ).rgb();
|
onSurface = color.toned( 80 ).rgb();
|
||||||
|
inverseSurface = color.toned( 90 ).rgb();
|
||||||
|
inverseOnSurface = color.toned( 20 ).rgb();
|
||||||
|
scrim = color.toned( 0 ).rgb();
|
||||||
shadow = color.toned( 0 ).rgb();
|
shadow = color.toned( 0 ).rgb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,11 @@ class QSK_MATERIAL3_EXPORT QskMaterial3Theme
|
||||||
|
|
||||||
QRgb surfaceContainerHighest;
|
QRgb surfaceContainerHighest;
|
||||||
|
|
||||||
|
QRgb inverseSurface;
|
||||||
|
QRgb inverseOnSurface;
|
||||||
|
QRgb inversePrimary;
|
||||||
|
|
||||||
|
QRgb scrim;
|
||||||
QRgb shadow;
|
QRgb shadow;
|
||||||
|
|
||||||
QskShadowMetrics elevation0;
|
QskShadowMetrics elevation0;
|
||||||
|
|
|
@ -74,15 +74,30 @@ InputPage::InputPage( QQuickItem* parent )
|
||||||
: Page( Qt::Horizontal, parent )
|
: Page( Qt::Horizontal, parent )
|
||||||
{
|
{
|
||||||
auto sliderH = new Slider( Qt::Horizontal );
|
auto sliderH = new Slider( Qt::Horizontal );
|
||||||
|
|
||||||
|
auto discreteSliderH = new Slider( Qt::Horizontal );
|
||||||
|
discreteSliderH->setSnap( true );
|
||||||
|
discreteSliderH->setStepSize( 10 );
|
||||||
|
discreteSliderH->setPageSize( 1 );
|
||||||
|
|
||||||
auto sliderV = new Slider( Qt::Vertical );
|
auto sliderV = new Slider( Qt::Vertical );
|
||||||
|
|
||||||
|
auto discreteSliderV = new Slider( Qt::Vertical );
|
||||||
|
discreteSliderV->setSnap( true );
|
||||||
|
discreteSliderV->setStepSize( 10 );
|
||||||
|
discreteSliderV->setPageSize( 2 );
|
||||||
|
|
||||||
auto inputBox = new InputBox();
|
auto inputBox = new InputBox();
|
||||||
|
|
||||||
auto gridBox = new QskGridBox( this );
|
auto gridBox = new QskGridBox( this );
|
||||||
|
gridBox->setSpacing( 30 );
|
||||||
|
gridBox->setMargins( 30 );
|
||||||
|
|
||||||
gridBox->addItem( sliderV, 0, 0, -1, 1 );
|
gridBox->addItem( sliderV, 0, 0, -1, 1 );
|
||||||
gridBox->addItem( sliderH, 0, 1, 1, -1 );
|
gridBox->addItem( discreteSliderV, 0, 1, -1, 1 );
|
||||||
gridBox->addItem( inputBox, 1, 1, -1, -1 );
|
gridBox->addItem( sliderH, 0, 2, 1, -1 );
|
||||||
|
gridBox->addItem( discreteSliderH, 1, 2, 1, -1 );
|
||||||
|
gridBox->addItem( inputBox, 2, 2, -1, -1 );
|
||||||
|
|
||||||
auto inputs = findChildren< QskBoundedValueInput* >();
|
auto inputs = findChildren< QskBoundedValueInput* >();
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,10 @@ QSK_SUBCONTROL( QskSlider, Fill )
|
||||||
QSK_SUBCONTROL( QskSlider, Scale )
|
QSK_SUBCONTROL( QskSlider, Scale )
|
||||||
QSK_SUBCONTROL( QskSlider, Handle )
|
QSK_SUBCONTROL( QskSlider, Handle )
|
||||||
QSK_SUBCONTROL( QskSlider, Ripple )
|
QSK_SUBCONTROL( QskSlider, Ripple )
|
||||||
|
QSK_SUBCONTROL( QskSlider, GrooveStopIndicators )
|
||||||
|
QSK_SUBCONTROL( QskSlider, FillStopIndicators )
|
||||||
|
QSK_SUBCONTROL( QskSlider, LabelContainer )
|
||||||
|
QSK_SUBCONTROL( QskSlider, LabelText )
|
||||||
|
|
||||||
QSK_SYSTEM_STATE( QskSlider, Pressed, QskAspect::FirstSystemState << 2 )
|
QSK_SYSTEM_STATE( QskSlider, Pressed, QskAspect::FirstSystemState << 2 )
|
||||||
|
|
||||||
|
@ -117,7 +121,15 @@ QSizeF QskSlider::handleSize() const
|
||||||
|
|
||||||
QRectF QskSlider::handleRect() const
|
QRectF QskSlider::handleRect() const
|
||||||
{
|
{
|
||||||
return subControlRect( QskSlider::Handle );
|
auto rect = subControlRect( Handle );
|
||||||
|
|
||||||
|
#if 1 // minimum handle strut size hardcoded here for now
|
||||||
|
const QSizeF strutSize( 60, 60 );
|
||||||
|
const auto w = qMax( ( strutSize.width() - rect.width() ) / 2, 0.0 );
|
||||||
|
const auto h = qMax( ( strutSize.height() - rect.height() ) / 2, 0.0 );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rect.marginsAdded( { w, h, w, h } );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSlider::mousePressEvent( QMouseEvent* event )
|
void QskSlider::mousePressEvent( QMouseEvent* event )
|
||||||
|
|
|
@ -25,7 +25,8 @@ class QSK_EXPORT QskSlider : public QskBoundedValueInput
|
||||||
using Inherited = QskBoundedValueInput;
|
using Inherited = QskBoundedValueInput;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QSK_SUBCONTROLS( Panel, Groove, Fill, Scale, Handle, Ripple )
|
QSK_SUBCONTROLS( Panel, Groove, Fill, Scale, Handle, Ripple, GrooveStopIndicators, FillStopIndicators,
|
||||||
|
LabelContainer, LabelText )
|
||||||
QSK_STATES( Pressed )
|
QSK_STATES( Pressed )
|
||||||
|
|
||||||
explicit QskSlider( QQuickItem* parent = nullptr );
|
explicit QskSlider( QQuickItem* parent = nullptr );
|
||||||
|
|
|
@ -10,28 +10,54 @@
|
||||||
#include "QskBoxBorderMetrics.h"
|
#include "QskBoxBorderMetrics.h"
|
||||||
#include "QskFunctions.h"
|
#include "QskFunctions.h"
|
||||||
|
|
||||||
static inline QRectF qskInnerPanelRect(
|
#include <QFontMetricsF>
|
||||||
const QskSlider* slider, const QRectF& contentsRect )
|
#include <QtMath>
|
||||||
|
|
||||||
|
using Q = QskSlider;
|
||||||
|
|
||||||
|
namespace
|
||||||
{
|
{
|
||||||
using Q = QskSlider;
|
inline QRectF qskInnerPanelRect(
|
||||||
|
const QskSlider* slider, const QRectF& contentsRect )
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
auto padding = slider->paddingHint( Q::Panel );
|
||||||
|
padding += slider->boxBorderMetricsHint( Q::Panel ).widths();
|
||||||
|
|
||||||
#if 1
|
auto r = slider->subControlRect( contentsRect, Q::Panel );
|
||||||
auto padding = slider->paddingHint( Q::Panel );
|
r = r.marginsRemoved( padding );
|
||||||
padding += slider->boxBorderMetricsHint( Q::Panel ).widths();
|
#else
|
||||||
|
r = slider->subControlContentsRect( contentsRect, Q::Panel );
|
||||||
|
#endif
|
||||||
|
|
||||||
auto r = slider->subControlRect( contentsRect, Q::Panel );
|
return r;
|
||||||
r = r.marginsRemoved( padding );
|
}
|
||||||
#else
|
|
||||||
r = slider->subControlContentsRect( contentsRect, Q::Panel );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return r;
|
QRectF qskInnerValueRect( const QskSlider* slider, const QRectF& contentsRect )
|
||||||
|
{
|
||||||
|
// For M3 the stop indicators have some padding related to the groove (and fill),
|
||||||
|
// so we use the rect between first and last stop indicator as authoritative for
|
||||||
|
// indicators, handle etc.
|
||||||
|
const auto grooveIndicatorMargins = slider->paddingHint( Q::GrooveStopIndicators );
|
||||||
|
const auto r = qskInnerPanelRect( slider, contentsRect ).marginsRemoved( grooveIndicatorMargins );
|
||||||
|
return r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QskSliderSkinlet::QskSliderSkinlet( QskSkin* skin )
|
QskSliderSkinlet::QskSliderSkinlet( QskSkin* skin )
|
||||||
: Inherited( skin )
|
: Inherited( skin )
|
||||||
{
|
{
|
||||||
setNodeRoles( { PanelRole, GrooveRole, FillRole, HandleRole, RippleRole } );
|
setNodeRoles( {
|
||||||
|
PanelRole,
|
||||||
|
GrooveRole,
|
||||||
|
FillRole,
|
||||||
|
FillStopIndicatorsRole,
|
||||||
|
GrooveStopIndicatorsRole,
|
||||||
|
HandleRole,
|
||||||
|
RippleRole,
|
||||||
|
LabelContainerRole,
|
||||||
|
LabelTextRole,
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskSliderSkinlet::~QskSliderSkinlet()
|
QskSliderSkinlet::~QskSliderSkinlet()
|
||||||
|
@ -43,39 +69,111 @@ QRectF QskSliderSkinlet::subControlRect( const QskSkinnable* skinnable,
|
||||||
{
|
{
|
||||||
const auto slider = static_cast< const QskSlider* >( skinnable );
|
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||||
|
|
||||||
if ( subControl == QskSlider::Panel )
|
if ( subControl == Q::Panel )
|
||||||
{
|
{
|
||||||
return panelRect( slider, contentsRect );
|
return panelRect( slider, contentsRect );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( subControl == QskSlider::Groove )
|
if ( subControl == Q::Groove )
|
||||||
{
|
{
|
||||||
return grooveRect( slider, contentsRect );
|
return grooveRect( slider, contentsRect );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( subControl == QskSlider::Fill )
|
if ( subControl == Q::Fill )
|
||||||
{
|
{
|
||||||
return fillRect( slider, contentsRect );
|
return fillRect( slider, contentsRect );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( subControl == QskSlider::Handle )
|
if ( subControl == Q::Handle )
|
||||||
{
|
{
|
||||||
return handleRect( slider, contentsRect );
|
return handleRect( slider, contentsRect );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( subControl == QskSlider::Scale )
|
if ( subControl == Q::Scale )
|
||||||
{
|
{
|
||||||
return scaleRect( slider, contentsRect );
|
return scaleRect( slider, contentsRect );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( subControl == QskSlider::Ripple )
|
if ( subControl == Q::Ripple )
|
||||||
{
|
{
|
||||||
return rippleRect( slider, contentsRect );
|
return rippleRect( slider, contentsRect );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( subControl == Q::LabelContainer )
|
||||||
|
{
|
||||||
|
return labelContainerRect( slider, contentsRect );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( subControl == Q::LabelText )
|
||||||
|
{
|
||||||
|
return labelContainerRect( slider, contentsRect );
|
||||||
|
}
|
||||||
|
|
||||||
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int QskSliderSkinlet::sampleCount( const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) const
|
||||||
|
{
|
||||||
|
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||||
|
|
||||||
|
if( slider->snap() )
|
||||||
|
{
|
||||||
|
const auto num = qCeil( slider->boundaryLength() / slider->stepSize() ) + 1;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ( subControl == Q::GrooveStopIndicators ) ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF QskSliderSkinlet::sampleRect( const QskSkinnable* skinnable, const QRectF& contentsRect,
|
||||||
|
QskAspect::Subcontrol subControl, int index ) const
|
||||||
|
{
|
||||||
|
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||||
|
|
||||||
|
auto r = qskInnerValueRect( slider, contentsRect );
|
||||||
|
|
||||||
|
const auto size = slider->strutSizeHint( subControl );
|
||||||
|
|
||||||
|
const auto filledPoints = qFloor( ( slider->value() - slider->minimum() ) / slider->stepSize() );
|
||||||
|
|
||||||
|
if( slider->snap())
|
||||||
|
{
|
||||||
|
if( slider->snap()
|
||||||
|
&& ( ( index >= filledPoints && subControl == Q::FillStopIndicators )
|
||||||
|
|| ( index < filledPoints && subControl == Q::GrooveStopIndicators ) ) )
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto pos = slider->snap() ? slider->minimum() + index * slider->stepSize() : slider->maximum();
|
||||||
|
|
||||||
|
if( slider->orientation() == Qt::Horizontal )
|
||||||
|
{
|
||||||
|
r.setTop( r.center().y() - size.height() / 2 );
|
||||||
|
const auto x = r.left() + slider->valueAsRatio( pos ) * r.width() - size.width() / 2;
|
||||||
|
r.setLeft( x );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r.setLeft( r.center().x() - size.width() / 2 );
|
||||||
|
const auto y = r.bottom() - slider->valueAsRatio( pos ) * r.height() - size.height() / 2;
|
||||||
|
r.setTop( y );
|
||||||
|
}
|
||||||
|
|
||||||
|
r.setHeight( size.height() );
|
||||||
|
r.setWidth( size.width() );
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
QskAspect::States QskSliderSkinlet::sampleStates( const QskSkinnable*, QskAspect::Subcontrol, int ) const
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
QSGNode* QskSliderSkinlet::updateSubNode(
|
QSGNode* QskSliderSkinlet::updateSubNode(
|
||||||
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
||||||
{
|
{
|
||||||
|
@ -85,42 +183,72 @@ QSGNode* QskSliderSkinlet::updateSubNode(
|
||||||
{
|
{
|
||||||
case PanelRole:
|
case PanelRole:
|
||||||
{
|
{
|
||||||
return updateBoxNode( slider, node, QskSlider::Panel );
|
return updateBoxNode( slider, node, Q::Panel );
|
||||||
}
|
}
|
||||||
|
|
||||||
case GrooveRole:
|
case GrooveRole:
|
||||||
{
|
{
|
||||||
return updateBoxNode( slider, node, QskSlider::Groove );
|
return updateBoxNode( slider, node, Q::Groove );
|
||||||
}
|
}
|
||||||
|
|
||||||
case FillRole:
|
case FillRole:
|
||||||
{
|
{
|
||||||
return updateBoxNode( slider, node, QskSlider::Fill );
|
return updateBoxNode( slider, node, Q::Fill );
|
||||||
|
}
|
||||||
|
|
||||||
|
case GrooveStopIndicatorsRole:
|
||||||
|
{
|
||||||
|
return updateSeriesNode( slider, Q::GrooveStopIndicators, node );
|
||||||
|
}
|
||||||
|
|
||||||
|
case FillStopIndicatorsRole:
|
||||||
|
{
|
||||||
|
return updateSeriesNode( slider, Q::FillStopIndicators, node );
|
||||||
}
|
}
|
||||||
|
|
||||||
case HandleRole:
|
case HandleRole:
|
||||||
{
|
{
|
||||||
return updateBoxNode( slider, node, QskSlider::Handle );
|
return updateBoxNode( slider, node, Q::Handle );
|
||||||
}
|
}
|
||||||
|
|
||||||
case RippleRole:
|
case RippleRole:
|
||||||
{
|
{
|
||||||
return updateBoxNode( slider, node, QskSlider::Ripple );
|
return updateBoxNode( slider, node, Q::Ripple );
|
||||||
|
}
|
||||||
|
|
||||||
|
case LabelContainerRole:
|
||||||
|
{
|
||||||
|
return updateBoxNode( slider, node, Q::LabelContainer );
|
||||||
|
}
|
||||||
|
|
||||||
|
case LabelTextRole:
|
||||||
|
{
|
||||||
|
const auto text = labelValue( slider );
|
||||||
|
return updateTextNode( slider, node, text, Q::LabelText );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSGNode* QskSliderSkinlet::updateSampleNode( const QskSkinnable* skinnable,
|
||||||
|
QskAspect::Subcontrol subControl, int index, QSGNode* node ) const
|
||||||
|
{
|
||||||
|
const auto slider = static_cast< const QskSlider* >( skinnable );
|
||||||
|
const auto rect = sampleRect( slider, slider->contentsRect(), subControl, index );
|
||||||
|
|
||||||
|
return updateBoxNode( skinnable, node, rect, subControl );
|
||||||
|
}
|
||||||
|
|
||||||
QRectF QskSliderSkinlet::panelRect(
|
QRectF QskSliderSkinlet::panelRect(
|
||||||
const QskSlider* slider, const QRectF& contentsRect ) const
|
const QskSlider* slider, const QRectF& contentsRect ) const
|
||||||
{
|
{
|
||||||
auto r = contentsRect;
|
auto r = contentsRect;
|
||||||
|
|
||||||
const qreal size = slider->metric( QskSlider::Panel | QskAspect::Size ); // 0: no hint
|
const qreal size = slider->metric( Q::Panel | QskAspect::Size ); // 0: no hint
|
||||||
if ( size > 0 && size < r.height() )
|
if ( size > 0 && size < r.height() )
|
||||||
{
|
{
|
||||||
const auto alignment = slider->alignmentHint( QskSlider::Panel );
|
const auto alignment = slider->alignmentHint( Q::Panel );
|
||||||
|
|
||||||
if ( slider->orientation() == Qt::Horizontal )
|
if ( slider->orientation() == Qt::Horizontal )
|
||||||
r = qskAlignedRectF( r, r.width(), size, alignment & Qt::AlignVertical_Mask );
|
r = qskAlignedRectF( r, r.width(), size, alignment & Qt::AlignVertical_Mask );
|
||||||
|
@ -161,33 +289,48 @@ QRectF QskSliderSkinlet::innerRect( const QskSlider* slider,
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF QskSliderSkinlet::grooveRect(
|
QRectF QskSliderSkinlet::grooveRect(
|
||||||
const QskSlider* slider, const QRectF& rect ) const
|
const QskSlider* slider, const QRectF& contentsRect ) const
|
||||||
{
|
{
|
||||||
return innerRect( slider, rect, QskSlider::Groove );
|
const auto r = qskInnerPanelRect( slider, contentsRect );
|
||||||
|
auto grooveRect = innerRect( slider, contentsRect, Q::Groove );
|
||||||
|
const auto handleRect = slider->subControlRect( Q::Handle );
|
||||||
|
|
||||||
|
if ( slider->orientation() == Qt::Horizontal )
|
||||||
|
{
|
||||||
|
grooveRect.setLeft( handleRect.right() );
|
||||||
|
grooveRect.setRight( r.right() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
grooveRect.setBottom( handleRect.top() );
|
||||||
|
grooveRect.setTop( r.top() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return grooveRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF QskSliderSkinlet::scaleRect(
|
QRectF QskSliderSkinlet::scaleRect(
|
||||||
const QskSlider* slider, const QRectF& rect ) const
|
const QskSlider* slider, const QRectF& rect ) const
|
||||||
{
|
{
|
||||||
return innerRect( slider, rect, QskSlider::Groove );
|
return innerRect( slider, rect, Q::Groove );
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF QskSliderSkinlet::fillRect(
|
QRectF QskSliderSkinlet::fillRect(
|
||||||
const QskSlider* slider, const QRectF& contentsRect ) const
|
const QskSlider* slider, const QRectF& contentsRect ) const
|
||||||
{
|
{
|
||||||
const auto r = qskInnerPanelRect( slider, contentsRect );
|
const auto r = qskInnerPanelRect( slider, contentsRect );
|
||||||
const auto pos = qBound( 0.0, slider->handlePosition(), 1.0 );
|
const auto handleRect = slider->subControlRect( Q::Handle );
|
||||||
|
|
||||||
auto fillRect = innerRect( slider, contentsRect, QskSlider::Fill );
|
auto fillRect = innerRect( slider, contentsRect, Q::Fill );
|
||||||
if ( slider->orientation() == Qt::Horizontal )
|
if ( slider->orientation() == Qt::Horizontal )
|
||||||
{
|
{
|
||||||
fillRect.setLeft( r.left() );
|
fillRect.setLeft( r.left() );
|
||||||
fillRect.setRight( r.left() + pos * r.width() );
|
fillRect.setRight( handleRect.left() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fillRect.setBottom( r.bottom() );
|
fillRect.setBottom( r.bottom() );
|
||||||
fillRect.setTop( r.bottom() - pos * r.height() );
|
fillRect.setTop( handleRect.bottom() );
|
||||||
}
|
}
|
||||||
|
|
||||||
return fillRect;
|
return fillRect;
|
||||||
|
@ -196,12 +339,10 @@ QRectF QskSliderSkinlet::fillRect(
|
||||||
QRectF QskSliderSkinlet::handleRect(
|
QRectF QskSliderSkinlet::handleRect(
|
||||||
const QskSlider* slider, const QRectF& contentsRect ) const
|
const QskSlider* slider, const QRectF& contentsRect ) const
|
||||||
{
|
{
|
||||||
using Q = QskSlider;
|
|
||||||
|
|
||||||
auto handleSize = slider->strutSizeHint( Q::Handle );
|
auto handleSize = slider->strutSizeHint( Q::Handle );
|
||||||
const auto pos = qBound( 0.0, slider->handlePosition(), 1.0 );
|
const auto pos = qBound( 0.0, slider->handlePosition(), 1.0 );
|
||||||
|
|
||||||
const auto r = qskInnerPanelRect( slider, contentsRect );
|
const auto r = qskInnerValueRect( slider, contentsRect );
|
||||||
auto center = r.center();
|
auto center = r.center();
|
||||||
|
|
||||||
if ( slider->orientation() == Qt::Horizontal )
|
if ( slider->orientation() == Qt::Horizontal )
|
||||||
|
@ -236,8 +377,8 @@ QRectF QskSliderSkinlet::handleRect(
|
||||||
QRectF QskSliderSkinlet::rippleRect(
|
QRectF QskSliderSkinlet::rippleRect(
|
||||||
const QskSlider* slider, const QRectF& rect ) const
|
const QskSlider* slider, const QRectF& rect ) const
|
||||||
{
|
{
|
||||||
const auto rippleSize = slider->strutSizeHint( QskSlider::Ripple );
|
const auto rippleSize = slider->strutSizeHint( Q::Ripple );
|
||||||
const auto handleSize = slider->strutSizeHint( QskSlider::Handle );
|
const auto handleSize = slider->strutSizeHint( Q::Handle );
|
||||||
|
|
||||||
const auto w = ( rippleSize.width() - handleSize.width() ) / 2;
|
const auto w = ( rippleSize.width() - handleSize.width() ) / 2;
|
||||||
const auto h = ( rippleSize.height() - handleSize.height() ) / 2;
|
const auto h = ( rippleSize.height() - handleSize.height() ) / 2;
|
||||||
|
@ -248,20 +389,67 @@ QRectF QskSliderSkinlet::rippleRect(
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRectF QskSliderSkinlet::labelContainerRect(
|
||||||
|
const QskSlider* slider, const QRectF& rect ) const
|
||||||
|
{
|
||||||
|
auto size = slider->strutSizeHint( Q::LabelContainer );
|
||||||
|
|
||||||
|
if( size.isEmpty() )
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QFontMetricsF fm( slider->effectiveFont( Q::LabelText ) );
|
||||||
|
const auto w = qskHorizontalAdvance( fm, labelValue( slider ) );
|
||||||
|
|
||||||
|
const auto padding = slider->paddingHint( Q::LabelContainer );
|
||||||
|
const auto h = fm.height() + padding.top() + padding.bottom();
|
||||||
|
|
||||||
|
size = size.expandedTo( { w, h } );
|
||||||
|
|
||||||
|
const auto hr = subControlRect( slider, rect, Q::Handle );
|
||||||
|
const auto margins = slider->marginHint( Q::LabelContainer );
|
||||||
|
|
||||||
|
qreal x, y;
|
||||||
|
|
||||||
|
if( slider->orientation() == Qt::Horizontal )
|
||||||
|
{
|
||||||
|
x = hr.center().x() - size.width() / 2;
|
||||||
|
y = hr.top() - margins.bottom() - size.height();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = hr.left() - size.width() - margins.left();
|
||||||
|
y = hr.center().y() - size.height() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QRectF r( x, y, size.width(), size.height() );
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
QSizeF QskSliderSkinlet::sizeHint( const QskSkinnable* skinnable,
|
QSizeF QskSliderSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||||
Qt::SizeHint which, const QSizeF& ) const
|
Qt::SizeHint which, const QSizeF& ) const
|
||||||
{
|
{
|
||||||
if ( which != Qt::PreferredSize )
|
if ( which != Qt::PreferredSize )
|
||||||
return QSizeF();
|
return QSizeF();
|
||||||
|
|
||||||
const auto slider = static_cast< const QskSlider* >( skinnable );
|
const auto panelHint = skinnable->strutSizeHint( Q::Panel );
|
||||||
|
const auto grooveHint = skinnable->strutSizeHint( Q::Groove );
|
||||||
|
const auto fillHint = skinnable->strutSizeHint( Q::Fill );
|
||||||
|
const auto handleHint = skinnable->strutSizeHint( Q::Handle );
|
||||||
|
|
||||||
// strutSizeHint( ... ) ???
|
auto hint = panelHint;
|
||||||
const qreal m1 = slider->metric( QskSlider::Panel | QskAspect::Size );
|
hint = hint.expandedTo( grooveHint );
|
||||||
const qreal m2 = 4 * m1;
|
hint = hint.expandedTo( fillHint );
|
||||||
|
hint = hint.expandedTo( handleHint );
|
||||||
|
|
||||||
return ( slider->orientation() == Qt::Horizontal )
|
return hint;
|
||||||
? QSizeF( m2, m1 ) : QSizeF( m1, m2 );
|
}
|
||||||
|
|
||||||
|
QString QskSliderSkinlet::labelValue( const QskSlider* slider ) const
|
||||||
|
{
|
||||||
|
return QString::number( slider->value(), 'f', 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "moc_QskSliderSkinlet.cpp"
|
#include "moc_QskSliderSkinlet.cpp"
|
||||||
|
|
|
@ -22,8 +22,12 @@ class QSK_EXPORT QskSliderSkinlet : public QskSkinlet
|
||||||
PanelRole,
|
PanelRole,
|
||||||
GrooveRole,
|
GrooveRole,
|
||||||
FillRole,
|
FillRole,
|
||||||
|
GrooveStopIndicatorsRole,
|
||||||
|
FillStopIndicatorsRole,
|
||||||
HandleRole,
|
HandleRole,
|
||||||
RippleRole,
|
RippleRole,
|
||||||
|
LabelContainerRole,
|
||||||
|
LabelTextRole,
|
||||||
|
|
||||||
RoleCount
|
RoleCount
|
||||||
};
|
};
|
||||||
|
@ -37,10 +41,21 @@ class QSK_EXPORT QskSliderSkinlet : public QskSkinlet
|
||||||
QSizeF sizeHint( const QskSkinnable*,
|
QSizeF sizeHint( const QskSkinnable*,
|
||||||
Qt::SizeHint, const QSizeF& ) const override;
|
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;
|
||||||
|
|
||||||
|
QskAspect::States sampleStates( const QskSkinnable*,
|
||||||
|
QskAspect::Subcontrol, int ) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QSGNode* updateSubNode( const QskSkinnable*,
|
QSGNode* updateSubNode( const QskSkinnable*,
|
||||||
quint8 nodeRole, QSGNode* ) const override;
|
quint8 nodeRole, QSGNode* ) const override;
|
||||||
|
|
||||||
|
QSGNode* updateSampleNode( const QskSkinnable*,
|
||||||
|
QskAspect::Subcontrol, int index, QSGNode* ) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QRectF panelRect( const QskSlider*, const QRectF& ) const;
|
QRectF panelRect( const QskSlider*, const QRectF& ) const;
|
||||||
QRectF grooveRect( const QskSlider*, const QRectF& ) const;
|
QRectF grooveRect( const QskSlider*, const QRectF& ) const;
|
||||||
|
@ -48,8 +63,11 @@ class QSK_EXPORT QskSliderSkinlet : public QskSkinlet
|
||||||
QRectF handleRect( const QskSlider*, const QRectF& ) const;
|
QRectF handleRect( const QskSlider*, const QRectF& ) const;
|
||||||
QRectF scaleRect( const QskSlider*, const QRectF& ) const;
|
QRectF scaleRect( const QskSlider*, const QRectF& ) const;
|
||||||
QRectF rippleRect( const QskSlider*, const QRectF& ) const;
|
QRectF rippleRect( const QskSlider*, const QRectF& ) const;
|
||||||
|
QRectF labelContainerRect( const QskSlider*, const QRectF& ) const;
|
||||||
|
|
||||||
QRectF innerRect( const QskSlider*, const QRectF&, QskAspect::Subcontrol ) const;
|
QRectF innerRect( const QskSlider*, const QRectF&, QskAspect::Subcontrol ) const;
|
||||||
|
|
||||||
|
QString labelValue( const QskSlider* ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue