QskSlider: Adapt to new Material3 style

( ValueLabel a.k.a Tooltip is not done yet )
This commit is contained in:
Uwe Rathmann 2024-11-07 17:31:14 +01:00
parent 05bf6cee70
commit 525ca3bd0e
7 changed files with 246 additions and 104 deletions

View File

@ -1437,11 +1437,11 @@ void Editor::setupSliderMetrics()
setPadding( Q::Panel | A::Horizontal, QskMargins( 0.5 * extent, 0 ) ); setPadding( Q::Panel | A::Horizontal, QskMargins( 0.5 * extent, 0 ) );
setPadding( Q::Panel | A::Vertical, QskMargins( 0, 0.5 * extent ) ); setPadding( Q::Panel | A::Vertical, QskMargins( 0, 0.5 * extent ) );
setMetric( Q::Groove | A::Size, 4_px ); for ( auto subControl : { Q::Groove, Q::Fill } )
setBoxShape( Q::Groove, 100, Qt::RelativeSize ); {
setMetric( subControl | A::Size, 4_px );
setMetric( Q::Fill | A::Size, 4_px ); setBoxShape( subControl, 100, Qt::RelativeSize );
setBoxShape( Q::Fill, 100, Qt::RelativeSize ); }
const auto shadowSpread = 1_px; const auto shadowSpread = 1_px;
@ -1503,8 +1503,9 @@ void Editor::setupSliderColors(
} }
grooveColor = rgbSolid( grooveColor, pal.background.solid.base ); grooveColor = rgbSolid( grooveColor, pal.background.solid.base );
setGradient( Q::Groove | section | state, grooveColor );
setGradient( Q::Groove | section | state, grooveColor );
setGradient( Q::Fill | section | state, grooveColor );
setGradient( Q::Handle | section | state, handleColor ); setGradient( Q::Handle | section | state, handleColor );
} }
} }

View File

@ -893,41 +893,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 );
@ -935,13 +934,24 @@ 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::Halo, 40_dp, 40_dp ); for( auto indicator : { Q::GrooveStopIndicators, Q::FillStopIndicators } )
setBoxShape( Q::Halo, 100, Qt::RelativeSize ); {
setGradient( Q::Halo, Qt::transparent ); setStrutSize( indicator, { 4_dp, 4_dp } );
setGradient( Q::Halo | Q::Hovered, m_pal.primary12 ); setBoxShape( indicator, 100, Qt::RelativeSize );
setGradient( Q::Halo | 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 );
// 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 );
} }
@ -1406,6 +1416,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();
} }
{ {
@ -1442,6 +1453,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();
} }
@ -1465,6 +1479,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();
} }
{ {
@ -1501,6 +1516,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();
} }

View File

@ -82,6 +82,11 @@ class QSK_MATERIAL3_EXPORT QskMaterial3Theme
QRgb surfaceContainerHighest; QRgb surfaceContainerHighest;
QRgb surfaceContainerHighest38; QRgb surfaceContainerHighest38;
QRgb inverseSurface;
QRgb inverseOnSurface;
QRgb inversePrimary;
QRgb scrim;
QRgb shadow; QRgb shadow;
QskShadowMetrics elevation0; QskShadowMetrics elevation0;

View File

@ -14,7 +14,8 @@ QSK_SUBCONTROL( QskSlider, Groove )
QSK_SUBCONTROL( QskSlider, Fill ) QSK_SUBCONTROL( QskSlider, Fill )
QSK_SUBCONTROL( QskSlider, Scale ) QSK_SUBCONTROL( QskSlider, Scale )
QSK_SUBCONTROL( QskSlider, Handle ) QSK_SUBCONTROL( QskSlider, Handle )
QSK_SUBCONTROL( QskSlider, Halo ) QSK_SUBCONTROL( QskSlider, GrooveStopIndicators )
QSK_SUBCONTROL( QskSlider, FillStopIndicators )
QSK_SYSTEM_STATE( QskSlider, Pressed, QskAspect::FirstSystemState << 2 ) QSK_SYSTEM_STATE( QskSlider, Pressed, QskAspect::FirstSystemState << 2 )
@ -117,7 +118,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 )

View File

@ -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, Halo ) QSK_SUBCONTROLS( Panel, Groove, Fill, Scale, Handle,
GrooveStopIndicators, FillStopIndicators )
QSK_STATES( Pressed ) QSK_STATES( Pressed )
explicit QskSlider( QQuickItem* parent = nullptr ); explicit QskSlider( QQuickItem* parent = nullptr );

View File

@ -10,28 +10,51 @@
#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, HaloRole } ); setNodeRoles( {
PanelRole,
GrooveRole,
FillRole,
FillStopIndicatorsRole,
GrooveStopIndicatorsRole,
HandleRole
} );
} }
QskSliderSkinlet::~QskSliderSkinlet() QskSliderSkinlet::~QskSliderSkinlet()
@ -43,37 +66,96 @@ 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::Halo ) 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() )
{ {
return haloRect( slider, contentsRect ); 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 {};
}
} }
return Inherited::subControlRect( skinnable, contentsRect, subControl ); 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(
@ -85,42 +167,56 @@ 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 HaloRole:
{
return updateBoxNode( slider, node, QskSlider::Halo );
} }
} }
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 +257,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 +307,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 )
@ -233,35 +342,23 @@ QRectF QskSliderSkinlet::handleRect(
return handleRect; return handleRect;
} }
QRectF QskSliderSkinlet::haloRect(
const QskSlider* slider, const QRectF& rect ) const
{
const auto haloSize = slider->strutSizeHint( QskSlider::Halo );
const auto handleSize = slider->strutSizeHint( QskSlider::Handle );
const auto w = ( haloSize.width() - handleSize.width() ) / 2;
const auto h = ( haloSize.height() - handleSize.height() ) / 2;
auto r = handleRect( slider, rect );
r = r.marginsAdded( { w, h, w, h } );
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 );
} }
#include "moc_QskSliderSkinlet.cpp" #include "moc_QskSliderSkinlet.cpp"

View File

@ -22,8 +22,9 @@ class QSK_EXPORT QskSliderSkinlet : public QskSkinlet
PanelRole, PanelRole,
GrooveRole, GrooveRole,
FillRole, FillRole,
GrooveStopIndicatorsRole,
FillStopIndicatorsRole,
HandleRole, HandleRole,
HaloRole,
RoleCount RoleCount
}; };
@ -37,17 +38,27 @@ 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;
QRectF fillRect( const QskSlider*, const QRectF& ) const; QRectF fillRect( const QskSlider*, const QRectF& ) const;
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 haloRect( const QskSlider*, const QRectF& ) const;
QRectF innerRect( const QskSlider*, const QRectF&, QskAspect::Subcontrol ) const; QRectF innerRect( const QskSlider*, const QRectF&, QskAspect::Subcontrol ) const;
}; };