2017-07-21 18:21:34 +02:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "QskSliderSkinlet.h"
|
|
|
|
#include "QskAspect.h"
|
2017-10-17 17:34:00 +02:00
|
|
|
#include "QskBoxBorderMetrics.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
#include "QskFunctions.h"
|
2018-08-03 08:15:28 +02:00
|
|
|
#include "QskSlider.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
static QMarginsF qskPadding(
|
|
|
|
const QskSlider* slider, QskAspect::Subcontrol subControl )
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
return slider->marginsHint( subControl | QskAspect::Padding ) +
|
|
|
|
slider->boxBorderMetricsHint( subControl ).widths();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QskSliderSkinlet::QskSliderSkinlet( QskSkin* skin )
|
|
|
|
: Inherited( skin )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
setNodeRoles( { PanelRole, GrooveRole, FillRole, HandleRole } );
|
|
|
|
}
|
|
|
|
|
|
|
|
QskSliderSkinlet::~QskSliderSkinlet() = default;
|
|
|
|
|
|
|
|
QRectF QskSliderSkinlet::subControlRect(
|
|
|
|
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) const
|
|
|
|
{
|
|
|
|
const auto slider = static_cast< const QskSlider* >( skinnable );
|
|
|
|
|
|
|
|
if ( subControl == QskSlider::Panel )
|
2017-09-01 11:55:55 +02:00
|
|
|
{
|
2017-07-21 18:21:34 +02:00
|
|
|
return panelRect( slider );
|
2017-09-01 11:55:55 +02:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
if ( subControl == QskSlider::Groove )
|
2017-09-01 11:55:55 +02:00
|
|
|
{
|
2017-07-21 18:21:34 +02:00
|
|
|
return grooveRect( slider );
|
2017-09-01 11:55:55 +02:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
if ( subControl == QskSlider::Fill )
|
2017-09-01 11:55:55 +02:00
|
|
|
{
|
2017-07-21 18:21:34 +02:00
|
|
|
return fillRect( slider );
|
2017-09-01 11:55:55 +02:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
if ( subControl == QskSlider::Handle )
|
2017-09-01 11:55:55 +02:00
|
|
|
{
|
2017-07-21 18:21:34 +02:00
|
|
|
return handleRect( slider );
|
2017-09-01 11:55:55 +02:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
if ( subControl == QskSlider::Scale )
|
2017-09-01 11:55:55 +02:00
|
|
|
{
|
2017-07-21 18:21:34 +02:00
|
|
|
return scaleRect( slider );
|
2017-09-01 11:55:55 +02:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
return Inherited::subControlRect( skinnable, subControl );
|
|
|
|
}
|
|
|
|
|
2017-09-01 11:55:55 +02:00
|
|
|
QSGNode* QskSliderSkinlet::updateSubNode(
|
|
|
|
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
|
|
|
{
|
|
|
|
const auto slider = static_cast< const QskSlider* >( skinnable );
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
switch ( nodeRole )
|
2017-09-01 11:55:55 +02:00
|
|
|
{
|
|
|
|
case PanelRole:
|
|
|
|
{
|
2017-10-17 17:34:00 +02:00
|
|
|
return updateBoxNode( slider, node, QskSlider::Panel );
|
2017-09-01 11:55:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
case GrooveRole:
|
|
|
|
{
|
2017-10-17 17:34:00 +02:00
|
|
|
return updateBoxNode( slider, node, QskSlider::Groove );
|
2017-09-01 11:55:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
case FillRole:
|
|
|
|
{
|
2017-10-17 17:34:00 +02:00
|
|
|
return updateBoxNode( slider, node, QskSlider::Fill );
|
2017-09-01 11:55:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
case HandleRole:
|
|
|
|
{
|
2017-10-17 17:34:00 +02:00
|
|
|
return updateBoxNode( slider, node, QskSlider::Handle );
|
2017-09-01 11:55:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
QRectF QskSliderSkinlet::panelRect( const QskSlider* slider ) const
|
|
|
|
{
|
|
|
|
using namespace QskAspect;
|
|
|
|
|
|
|
|
const QskAspect::Subcontrol subControl = QskSlider::Panel;
|
|
|
|
|
|
|
|
qreal size = slider->metric( subControl | Size ); // 0: no hint
|
|
|
|
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
We use MinimumHeight/MaximumHeight/Size for the "thickness" of
|
|
|
|
to slider even if "Height" is not the expected value for
|
|
|
|
vertical sliders. Maybe we should have the orientation as an aspect bit ?
|
|
|
|
*/
|
|
|
|
|
|
|
|
const qreal minSize = slider->metric( subControl | MinimumHeight );
|
|
|
|
const qreal maxSize = slider->metric( subControl | MaximumHeight );
|
|
|
|
|
|
|
|
size = qMax( size, minSize );
|
|
|
|
if ( maxSize > minSize )
|
|
|
|
size = qMin( size, maxSize );
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF r = slider->contentsRect();
|
|
|
|
|
|
|
|
if ( size > 0 && size < r.height() )
|
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
const Qt::Alignment alignment =
|
|
|
|
slider->flagHint< Qt::Alignment >( subControl | Alignment );
|
2017-07-21 18:21:34 +02: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;
|
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
QRectF QskSliderSkinlet::innerRect(
|
|
|
|
const QskSlider* slider, QskAspect::Subcontrol subControl ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
using namespace QskAspect;
|
|
|
|
|
|
|
|
QRectF r = subControlRect( slider, QskSlider::Panel );
|
|
|
|
r = r.marginsRemoved( qskPadding( slider, QskSlider::Panel ) );
|
|
|
|
|
|
|
|
QskSkinHintStatus status;
|
|
|
|
|
|
|
|
qreal thickness = slider->metric( subControl | Size, &status );
|
|
|
|
|
|
|
|
if ( slider->orientation() == Qt::Horizontal )
|
|
|
|
{
|
|
|
|
if ( status.isValid() && thickness < r.height() )
|
|
|
|
{
|
|
|
|
r.setTop( r.center().y() - 0.5 * thickness );
|
|
|
|
r.setHeight( thickness );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( status.isValid() && thickness < r.width() )
|
|
|
|
{
|
|
|
|
r.setLeft( r.center().x() - 0.5 * thickness );
|
|
|
|
r.setWidth( thickness );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF QskSliderSkinlet::grooveRect( const QskSlider* slider ) const
|
|
|
|
{
|
|
|
|
return innerRect( slider, QskSlider::Groove );
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF QskSliderSkinlet::scaleRect( const QskSlider* slider ) const
|
|
|
|
{
|
|
|
|
return innerRect( slider, QskSlider::Groove );
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF QskSliderSkinlet::fillRect( const QskSlider* slider ) const
|
|
|
|
{
|
|
|
|
using namespace QskAspect;
|
|
|
|
|
|
|
|
QRectF r = subControlRect( slider, QskSlider::Panel );
|
|
|
|
r = r.marginsRemoved( qskPadding( slider, QskSlider::Panel ) );
|
|
|
|
|
|
|
|
qreal pos = slider->metric( QskSlider::Handle | Position );
|
|
|
|
pos = qBound( 0.0, pos, 1.0 );
|
|
|
|
|
|
|
|
QRectF fillRect = innerRect( slider, QskSlider::Fill );
|
|
|
|
if ( slider->orientation() == Qt::Horizontal )
|
|
|
|
{
|
|
|
|
fillRect.setLeft( r.left() );
|
|
|
|
fillRect.setRight( r.left() + pos * r.width() );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fillRect.setBottom( r.bottom() );
|
|
|
|
fillRect.setTop( r.bottom() - pos * r.height() );
|
|
|
|
}
|
|
|
|
|
|
|
|
return fillRect;
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF QskSliderSkinlet::handleRect( const QskSlider* slider ) const
|
|
|
|
{
|
|
|
|
using namespace QskAspect;
|
|
|
|
|
|
|
|
QRectF r = subControlRect( slider, QskSlider::Panel );
|
|
|
|
r = r.marginsRemoved( qskPadding( slider, QskSlider::Panel ) );
|
|
|
|
|
|
|
|
const bool isHorizontal = slider->orientation() == Qt::Horizontal;
|
|
|
|
|
|
|
|
qreal thickness;
|
|
|
|
|
|
|
|
{
|
|
|
|
QskSkinHintStatus status;
|
|
|
|
|
|
|
|
thickness = slider->metric( QskSlider::Handle | Size, &status );
|
|
|
|
if ( !status.isValid() )
|
|
|
|
thickness = isHorizontal ? r.height() : r.width();
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF handleRect( 0, 0, thickness, thickness );
|
|
|
|
if ( thickness > 0 )
|
2017-10-17 17:34:00 +02:00
|
|
|
{
|
|
|
|
handleRect = handleRect.marginsRemoved(
|
|
|
|
slider->marginsHint( QskSlider::Handle | QskAspect::Margin ) );
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
qreal pos = slider->metric( QskSlider::Handle | Position );
|
|
|
|
pos = qBound( 0.0, pos, 1.0 );
|
|
|
|
|
|
|
|
if ( slider->orientation() == Qt::Horizontal )
|
|
|
|
{
|
|
|
|
pos = r.left() + pos * r.width();
|
|
|
|
handleRect.moveCenter( QPointF( pos, r.center().y() ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pos = r.bottom() - pos * r.height();
|
|
|
|
handleRect.moveCenter( QPointF( r.center().x(), pos ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
return handleRect;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "moc_QskSliderSkinlet.cpp"
|