qskinny/src/controls/QskSwitchButtonSkinlet.cpp

197 lines
5.1 KiB
C++
Raw Normal View History

2021-08-02 17:17:04 +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
2021-08-02 17:17:04 +00:00
*****************************************************************************/
2021-08-02 11:22:37 +00:00
#include "QskSwitchButtonSkinlet.h"
2021-08-27 07:45:24 +00:00
#include "QskSwitchButton.h"
2021-08-02 17:17:04 +00:00
using Q = QskSwitchButton;
static inline qreal qskEffectivePosition( const QskSwitchButton* switchButton )
{
2021-12-29 16:05:29 +00:00
auto pos = switchButton->positionHint( QskSwitchButton::Handle );
pos = qBound( 0.0, pos, 1.0 );
if( switchButton->isInverted() )
pos = 1.0 - pos;
if ( switchButton->orientation() == Qt::Horizontal )
{
if( switchButton->layoutMirroring() )
pos = 1.0 - pos;
}
return pos;
}
static QSizeF qskIconSize( const QskSwitchButton* button )
{
if( button->iconMode() == Q::NoIcon
|| ( button->iconMode() == Q::ShowIconWhenSelected && !button->isChecked() ) )
{
return {};
}
else
{
return button->strutSizeHint( Q::Icon );
}
}
2021-08-02 17:17:04 +00:00
QskSwitchButtonSkinlet::QskSwitchButtonSkinlet( QskSkin* skin )
2021-08-02 11:22:37 +00:00
: Inherited( skin )
{
setNodeRoles( { GrooveRole, HandleRole, IconRole } );
2021-08-02 11:22:37 +00:00
}
2021-08-02 17:17:04 +00:00
QskSwitchButtonSkinlet::~QskSwitchButtonSkinlet()
{
}
2021-08-02 11:22:37 +00:00
QRectF QskSwitchButtonSkinlet::subControlRect( const QskSkinnable* skinnable,
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
2021-08-02 11:22:37 +00:00
{
const auto button = static_cast< const Q* >( skinnable );
if ( subControl == Q::Groove )
{
return grooveRect( button, contentsRect );
}
2021-08-02 17:17:04 +00:00
if ( subControl == Q::Handle )
2021-08-02 11:22:37 +00:00
{
return handleRect( button, contentsRect );
}
2021-08-02 11:22:37 +00:00
if ( subControl == Q::Icon )
{
return iconRect( button, contentsRect );
}
2021-08-02 11:22:37 +00:00
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
2021-08-02 11:22:37 +00:00
QSizeF QskSwitchButtonSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint which, const QSizeF& ) const
{
if ( which != Qt::PreferredSize )
return QSizeF();
2021-08-02 11:22:37 +00:00
2024-10-23 11:25:23 +00:00
const auto grooveHint = skinnable->strutSizeHint( QskSwitchButton::Groove );
const auto handleHint = skinnable->strutSizeHint( QskSwitchButton::Handle );
2021-08-27 07:09:10 +00:00
auto hint = grooveHint;
2021-08-27 07:09:10 +00:00
hint = hint.expandedTo( handleHint );
2021-08-02 17:17:04 +00:00
return hint;
}
2021-08-02 17:17:04 +00:00
QSGNode* QskSwitchButtonSkinlet::updateSubNode( const QskSkinnable* skinnable,
quint8 nodeRole, QSGNode* node ) const
{
switch ( nodeRole )
{
case HandleRole:
return updateBoxNode( skinnable, node, Q::Handle );
case IconRole:
return updateSymbolNode( skinnable, node, Q::Icon );
case GrooveRole:
return updateBoxNode( skinnable, node, Q::Groove );
2021-08-02 11:22:37 +00:00
}
2021-08-02 17:17:04 +00:00
return Inherited::updateSubNode( skinnable, nodeRole, node );
}
2021-08-02 17:17:04 +00:00
QRectF QskSwitchButtonSkinlet::grooveRect(
const QskSwitchButton* button, const QRectF& contentsRect ) const
{
auto size = button->strutSizeHint( Q::Groove );
2021-08-02 17:17:04 +00:00
if ( button->orientation() == Qt::Vertical )
{
if ( size.height() < 0.0 )
{
const auto handleSize = button->strutSizeHint( Q::Handle );
size.setHeight( 2 * handleSize.height() );
2021-08-02 11:22:37 +00:00
}
}
else
{
if ( size.width() < 0.0 )
2021-08-02 11:22:37 +00:00
{
const auto handleSize = button->strutSizeHint( Q::Handle );
size.setWidth( 2 * handleSize.width() );
2021-08-02 11:22:37 +00:00
}
}
size = size.expandedTo( QSize( 0.0, 0.0 ) );
2021-08-04 07:31:16 +00:00
QRectF r;
r.setSize( size );
r.moveCenter( contentsRect.center() );
return r;
2021-08-02 11:22:37 +00:00
}
QRectF QskSwitchButtonSkinlet::handleRect(
const QskSwitchButton* button, const QRectF& contentsRect ) const
2021-08-02 11:22:37 +00:00
{
const auto grooveRect = subControlRect( button, contentsRect, Q::Groove );
const auto pos = qskEffectivePosition( button );
2021-08-02 17:17:04 +00:00
auto size = button->strutSizeHint( Q::Handle );
2021-08-02 17:17:04 +00:00
qreal cx, cy;
2021-08-02 11:22:37 +00:00
if( button->orientation() == Qt::Vertical )
{
const qreal y0 = grooveRect.y() + 0.5 * size.height();
const qreal h = grooveRect.height() - size.height();
2021-08-02 11:22:37 +00:00
cx = grooveRect.x() + 0.5 * grooveRect.width();
cy = y0 + pos * h;
}
else
2021-08-02 11:22:37 +00:00
{
const qreal x0 = grooveRect.x() + 0.5 * size.width();
const qreal w = grooveRect.width() - size.width();
2021-08-02 11:22:37 +00:00
cx = x0 + pos * w;
cy = grooveRect.y() + 0.5 * grooveRect.height();
2021-08-02 11:22:37 +00:00
}
auto iconSize = qskIconSize( button );
if( !iconSize.isNull() )
{
auto padding = button->paddingHint( Q::Icon );
// need to compensate for the margins,
// which might differ between states:
auto margins = button->marginHint( Q::Handle );
iconSize = iconSize.grownBy( padding ).grownBy( margins );
size = size.expandedTo( iconSize );
}
QRectF r;
r.setSize( size );
r.moveCenter( QPointF( cx, cy ) );
return r;
2021-08-02 11:22:37 +00:00
}
2021-08-02 17:17:04 +00:00
QRectF QskSwitchButtonSkinlet::iconRect( const QskSwitchButton* button, const QRectF& contentsRect ) const
{
QRectF rect;
rect.setSize( qskIconSize( button ) );
const auto hr = handleRect( button, contentsRect );
rect.moveCenter( hr.center() );
return rect;
}
2021-08-02 17:17:04 +00:00
#include "moc_QskSwitchButtonSkinlet.cpp"