qskinny/src/controls/QskCheckBoxSkinlet.cpp

137 lines
3.6 KiB
C++
Raw Normal View History

/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskCheckBoxSkinlet.h"
#include "QskCheckBox.h"
#include <QSGFlatColorMaterial>
#include <qsgnode.h>
namespace
{
class Tick : public QSGGeometryNode
{
public:
2022-04-04 18:32:17 +02:00
Tick()
: geometry( QSGGeometry::defaultAttributes_Point2D(), 3 )
{
geometry.setDrawingMode( QSGGeometry::DrawLineStrip );
geometry.setLineWidth( 2 );
setGeometry( &geometry );
setMaterial( &material );
}
2022-04-04 18:32:17 +02:00
void setColor( const QColor& color )
{
material.setColor( color );
markDirty( QSGNode::DirtyMaterial );
}
2022-04-04 18:32:17 +02:00
void makeTick( const QRectF& rect )
{
2022-04-04 18:32:17 +02:00
const auto x = rect.x();
const auto y = rect.y();
auto vertexData = geometry.vertexDataAsPoint2D();
2022-04-04 18:32:17 +02:00
vertexData[0].set( x, y + rect.height() / 2 );
vertexData[1].set( x + rect.width() / 3, y + rect.height() );
vertexData[2].set( x + rect.width(), y );
markDirty( QSGNode::DirtyGeometry );
}
2022-04-04 18:32:17 +02:00
void makePartially( const QRectF& rect )
{
2022-04-04 18:32:17 +02:00
const auto x = rect.x();
const auto y = rect.y();
auto vertexData = geometry.vertexDataAsPoint2D();
2022-04-04 18:32:17 +02:00
vertexData[0].set( x, y + rect.height() / 2 );
vertexData[1].set( x, y + rect.height() / 2 );
vertexData[2].set( x + rect.width(), y + rect.height() / 2 );
markDirty( QSGNode::DirtyGeometry );
}
private:
QSGFlatColorMaterial material;
QSGGeometry geometry;
};
}
QskCheckBoxSkinlet::QskCheckBoxSkinlet( QskSkin* skin )
: QskSkinlet( skin )
{
setNodeRoles( { BoxRole, TickRole } );
}
QskCheckBoxSkinlet::~QskCheckBoxSkinlet()
{
}
QRectF QskCheckBoxSkinlet::subControlRect(
const QskSkinnable*, const QRectF& contentsRect, QskAspect::Subcontrol ) const
{
return contentsRect;
}
QSGNode* QskCheckBoxSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{
switch( nodeRole )
{
case BoxRole:
{
return updateBoxNode( skinnable, node, QskCheckBox::Box );
}
case TickRole:
{
auto checkBox = static_cast< const QskCheckBox* >( skinnable );
return updateTickNode( checkBox, node );
}
}
return Inherited::updateSubNode( skinnable, nodeRole, node );
}
QSGNode* QskCheckBoxSkinlet::updateTickNode(
const QskCheckBox* checkBox, QSGNode* node ) const
{
using Q = QskCheckBox;
2022-04-04 18:32:17 +02:00
if ( checkBox->checkState() == Qt::Unchecked )
return nullptr;
auto rect = checkBox->subControlRect( Q::Tick );
rect = rect.marginsRemoved( checkBox->marginHint( Q::Tick ) );
auto tick = static_cast< Tick* >( node );
if ( tick == nullptr )
2022-04-04 18:32:17 +02:00
tick = new Tick();
2022-04-04 18:32:17 +02:00
if ( checkBox->checkState() == Qt::PartiallyChecked )
{
2022-04-04 18:32:17 +02:00
tick->setColor( checkBox->color( Q::Tick | Q::PartiallyChecked ) );
tick->makePartially( rect );
}
else
{
tick->setColor( checkBox->color( Q::Tick | Q::Checked ) );
tick->makeTick( rect );
}
return tick;
}
QSizeF QskCheckBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint, const QSizeF& ) const
{
return skinnable->strutSizeHint( QskCheckBox::Box );
}