qskinny/src/controls/QskSliderSkinlet.cpp

266 lines
7.7 KiB
C++
Raw Normal View History

2017-07-21 16:21:34 +00:00
/******************************************************************************
2024-01-17 13:31:45 +00:00
* QSkinny - Copyright (C) The authors
2023-04-06 07:23:37 +00:00
* SPDX-License-Identifier: BSD-3-Clause
2017-07-21 16:21:34 +00:00
*****************************************************************************/
#include "QskSliderSkinlet.h"
2018-08-03 06:30:23 +00:00
#include "QskSlider.h"
2017-07-21 16:21:34 +00:00
#include "QskFunctions.h"
using Q = QskSlider;
2024-11-18 15:15:50 +00:00
static QRectF qskInnerRect( const QskSlider* slider,
const QRectF& contentsRect, QskAspect::Subcontrol subControl )
2017-07-21 16:21:34 +00:00
{
2024-11-18 15:15:50 +00:00
auto r = slider->subControlContentsRect( contentsRect, Q::Panel );
2020-12-17 15:14:56 +00:00
2024-11-18 15:15:50 +00:00
QskSkinHintStatus status;
2020-12-17 15:14:56 +00:00
2024-11-18 15:15:50 +00:00
const qreal extent = slider->metric( subControl | QskAspect::Size, &status );
2020-12-17 15:14:56 +00:00
2024-11-18 15:15:50 +00:00
if ( slider->orientation() == Qt::Horizontal )
{
2024-11-18 15:15:50 +00:00
if ( status.isValid() && ( extent < r.height() ) )
{
r.setTop( r.center().y() - 0.5 * extent );
r.setHeight( extent );
}
}
2024-11-18 15:15:50 +00:00
else
{
if ( status.isValid() && ( extent < r.width() ) )
{
r.setLeft( r.center().x() - 0.5 * extent );
r.setWidth( extent );
}
}
return r;
2017-07-21 16:21:34 +00:00
}
2018-08-03 06:15:28 +00:00
QskSliderSkinlet::QskSliderSkinlet( QskSkin* skin )
: Inherited( skin )
2017-07-21 16:21:34 +00:00
{
2024-11-18 15:15:50 +00:00
setNodeRoles( { PanelRole, GrooveRole, FillRole, TicksRole, HandleRole } );
2017-07-21 16:21:34 +00:00
}
QskSliderSkinlet::~QskSliderSkinlet()
{
}
2017-07-21 16:21:34 +00:00
QRectF QskSliderSkinlet::subControlRect( const QskSkinnable* skinnable,
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
2017-07-21 16:21:34 +00:00
{
const auto slider = static_cast< const QskSlider* >( skinnable );
if ( subControl == Q::Panel )
return panelRect( slider, contentsRect );
2017-07-21 16:21:34 +00:00
if ( subControl == Q::Groove )
2024-11-18 15:15:50 +00:00
return qskInnerRect( slider, contentsRect, Q::Groove );
2017-07-21 16:21:34 +00:00
if ( subControl == Q::Fill )
return fillRect( slider, contentsRect );
2024-11-18 15:15:50 +00:00
if ( subControl == Q::Scale )
return subControlRect( skinnable, contentsRect, Q::Groove );
2017-07-21 16:21:34 +00:00
if ( subControl == Q::Handle )
return handleRect( slider, contentsRect );
2017-07-21 16:21:34 +00:00
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
2017-09-01 09:55:55 +00:00
QSGNode* QskSliderSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{
const auto slider = static_cast< const QskSlider* >( skinnable );
2018-08-03 06:15:28 +00:00
switch ( nodeRole )
2017-09-01 09:55:55 +00:00
{
case PanelRole:
return updateBoxNode( slider, node, Q::Panel );
2017-09-01 09:55:55 +00:00
case GrooveRole:
return updateBoxNode( slider, node, Q::Groove );
2017-09-01 09:55:55 +00:00
case FillRole:
return updateBoxNode( slider, node, Q::Fill );
case HandleRole:
return updateBoxNode( slider, node, Q::Handle );
2024-11-21 16:59:54 +00:00
case TicksRole:
return updateSeriesNode( slider, Q::Tick, node );
2017-09-01 09:55:55 +00:00
}
return Inherited::updateSubNode( skinnable, nodeRole, node );
}
2024-11-21 16:59:54 +00:00
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
2017-07-21 16:21:34 +00:00
{
auto r = contentsRect;
2017-07-21 16:21:34 +00:00
const qreal size = slider->metric( Q::Panel | QskAspect::Size ); // 0: no hint
2017-07-21 16:21:34 +00:00
if ( size > 0 && size < r.height() )
{
const auto alignment = slider->alignmentHint( Q::Panel );
2017-07-21 16:21:34 +00:00
if ( slider->orientation() == Qt::Horizontal )
r = qskAlignedRectF( r, r.width(), size, alignment & Qt::AlignVertical_Mask );
else
r = qskAlignedRectF( r, size, r.height(), alignment & Qt::AlignHorizontal_Mask );
}
return r;
}
2024-11-18 15:15:50 +00:00
QRectF QskSliderSkinlet::fillRect(
const QskSlider* slider, const QRectF& contentsRect ) const
2017-07-21 16:21:34 +00:00
{
2024-11-18 15:15:50 +00:00
const auto pos = qBound( 0.0, slider->handlePosition(), 1.0 );
2024-11-18 15:15:50 +00:00
auto r = qskInnerRect( slider, contentsRect, QskSlider::Fill );
2017-07-21 16:21:34 +00:00
2024-11-18 15:15:50 +00:00
auto scaleRect = subControlRect( slider, contentsRect, Q::Scale );
2017-07-21 16:21:34 +00:00
if ( slider->orientation() == Qt::Horizontal )
2024-11-18 15:15:50 +00:00
r.setRight( scaleRect.left() + pos * scaleRect.width() );
2017-07-21 16:21:34 +00:00
else
2024-11-18 15:15:50 +00:00
r.setTop( scaleRect.bottom() - pos * scaleRect.height() );
2017-07-21 16:21:34 +00:00
2024-11-18 15:15:50 +00:00
return r;
2017-07-21 16:21:34 +00:00
}
QRectF QskSliderSkinlet::handleRect(
const QskSlider* slider, const QRectF& contentsRect ) const
2017-07-21 16:21:34 +00:00
{
2020-12-17 15:14:56 +00:00
auto handleSize = slider->strutSizeHint( Q::Handle );
const auto pos = qBound( 0.0, slider->handlePosition(), 1.0 );
2017-07-21 16:21:34 +00:00
2024-11-18 15:15:50 +00:00
const auto r = subControlRect( slider, contentsRect, Q::Scale );
2020-12-17 15:14:56 +00:00
auto center = r.center();
2017-07-21 16:21:34 +00:00
2020-12-17 15:14:56 +00:00
if ( slider->orientation() == Qt::Horizontal )
{
2020-12-17 15:14:56 +00:00
if ( handleSize.height() < 0.0 )
handleSize.setHeight( r.height() );
2017-07-21 16:21:34 +00:00
2020-12-17 15:14:56 +00:00
if ( handleSize.width() < 0.0 )
handleSize.setWidth( handleSize.height() );
2017-07-21 16:21:34 +00:00
2020-12-17 15:14:56 +00:00
center.setX( r.left() + pos * r.width() );
2017-07-21 16:21:34 +00:00
}
else
{
2020-12-17 15:14:56 +00:00
if ( handleSize.width() < 0.0 )
handleSize.setWidth( r.width() );
if ( handleSize.height() < 0.0 )
handleSize.setHeight( handleSize.width() );
center.setY( r.bottom() - pos * r.height() );
2017-07-21 16:21:34 +00:00
}
2020-12-17 15:14:56 +00:00
QRectF handleRect( 0, 0, handleSize.width(), handleSize.height() );
handleRect.moveCenter( center );
2017-07-21 16:21:34 +00:00
return handleRect;
}
2024-11-21 16:59:54 +00:00
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
{
if ( which != Qt::PreferredSize )
return QSizeF();
2024-11-18 15:15:50 +00:00
auto hint = skinnable->strutSizeHint( Q::Panel );
hint = hint.expandedTo( skinnable->strutSizeHint( Q::Groove ) );
hint = hint.expandedTo( skinnable->strutSizeHint( Q::Fill ) );
hint = hint.expandedTo( skinnable->strutSizeHint( Q::Handle ) );
return hint;
}
2017-07-21 16:21:34 +00:00
#include "moc_QskSliderSkinlet.cpp"