Add text label to QskCheckBox

This commit is contained in:
Clemens Manert 2022-04-24 19:05:12 +02:00
parent 045798d084
commit e70851dbc8
No known key found for this signature in database
GPG Key ID: 9197EAE8F85E3A18
6 changed files with 221 additions and 30 deletions

View File

@ -191,20 +191,24 @@ void Editor::setupCheckBox()
using A = QskAspect;
using Q = QskCheckBox;
const qreal size = qskDpiScaled( 18 );
const qreal sizeTic = qskDpiScaled( 16 ); // - Border;
const qreal sizeBox = qskDpiScaled( 26 );
setStrutSize( Q::Panel, size, size );
setPadding( Q::Panel, 3 );
setStrutSize( Q::IndicatorTic, sizeTic, sizeTic );
setStrutSize( Q::IndicatorBox, sizeBox, sizeBox);
setBoxShape( Q::Panel, 2 );
setMargin( Q::Text, QskMargins( qskDpiScaled( 5 ), 0,qskDpiScaled( 5 ), 0 ) );
setMargin( Q::IndicatorTic, QskMargins( qskDpiScaled( 5 ) ) );
setGradient( Q::Panel, m_pal.baseColor);
setGradient( Q::Panel | Q::Checked, m_pal.accentColor );
setGradient( Q::Panel | Q::Checked | Q::Disabled, QskRgb::Grey );
setBoxShape( Q::IndicatorBox, qskDpiScaled( 3 ) );
setBoxBorderMetrics( Q::IndicatorBox, qskDpiScaled( 1 ) );
setBoxBorderColors( Q::IndicatorBox, m_pal.darker125 );
setColor( Q::Indicator, m_pal.contrastColor );
setGradient( Q::IndicatorBox | Q::Checked, m_pal.accentColor);
setColor( Q::IndicatorTic, m_pal.lighter200 );
setGradient( Q::Panel, m_pal.baseColor );
setAnimation( Q::Panel | A::Color, qskDuration );
setAnimation( Q::IndicatorBox | A::Color, qskDuration );
}
void Editor::setupBox()

View File

@ -303,21 +303,27 @@ void Editor::setupCheckBox()
using A = QskAspect;
using Q = QskCheckBox;
const qreal size = qskDpiScaled( 26 );
const qreal sizeTic = qskDpiScaled( 24 ); // - Border;
const qreal sizeBox = qskDpiScaled( 26 );
setStrutSize( Q::Panel, size, size );
setStrutSize( Q::IndicatorTic, sizeTic, sizeTic );
setStrutSize( Q::IndicatorBox, sizeBox, sizeBox);
setPadding( Q::Panel, qskDpiScaled( 5 ) );
setBoxShape( Q::Panel, qskDpiScaled( 3 ) );
setBoxBorderMetrics( Q::Panel, qskDpiScaled( 1 ) );
setMargin( Q::Text, QskMargins(qskDpiScaled(5),0,qskDpiScaled(5),0) );
setMargin( Q::IndicatorTic, QskMargins( qskDpiScaled( 1 ) ) );
setBoxBorderColors( Q::Panel, m_pal.darker125 );
setGradient( Q::Panel, m_pal.lighter135 );
setGradient( Q::Panel | Q::Checked, m_pal.highlighted );
setBoxShape( Q::IndicatorBox, qskDpiScaled( 3 ) );
setBoxBorderMetrics( Q::IndicatorBox, qskDpiScaled( 1 ) );
setBoxBorderColors( Q::IndicatorBox, m_pal.darker125 );
setColor( Q::Indicator, m_pal.lighter135 );
setGradient( Q::IndicatorBox, m_pal.lighter135 );
setGradient( Q::IndicatorBox | Q::Checked, m_pal.highlighted );
setAnimation( Q::Panel | A::Color, qskDuration );
setGradient( Q::IndicatorTic, m_pal.lighter135 );
setGradient( Q::Panel, m_pal.base );
setAnimation( Q::IndicatorBox | A::Color, qskDuration );
}
void Editor::setupPopup()

View File

@ -6,11 +6,21 @@
#include "QskCheckBox.h"
#include "QskAspect.h"
#include "QskTextOptions.h"
QSK_SUBCONTROL( QskCheckBox, Panel )
QSK_SUBCONTROL( QskCheckBox, Indicator )
QSK_SUBCONTROL( QskCheckBox, IndicatorBox )
QSK_SUBCONTROL( QskCheckBox, IndicatorTic )
QSK_SUBCONTROL( QskCheckBox, Text )
class QskCheckBox::PrivateData {
public:
QString text;
QskTextOptions textOptions;
};
QskCheckBox::QskCheckBox( QQuickItem* parent )
: Inherited( parent )
: Inherited( parent ), m_data( new PrivateData )
{
setAcceptHoverEvents( true );
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
@ -25,4 +35,34 @@ bool QskCheckBox::isCheckable() const
return true;
}
QString QskCheckBox::text() const {
return m_data->text;
}
QskTextOptions QskCheckBox::textOptions() const {
return m_data->textOptions;
}
void QskCheckBox::setText( const QString& text ) {
if( m_data->text == text )
{
return;
}
m_data->text = text;
Q_EMIT textChanged( text );
}
void QskCheckBox::setTextOptions( const QskTextOptions& textOptions) {
if( m_data->textOptions == textOptions )
{
return;
}
m_data->textOptions = textOptions;
Q_EMIT textOptionsChanged( textOptions );
}
#include "moc_QskCheckBox.cpp"

View File

@ -8,19 +8,42 @@
#include "QskAbstractButton.h"
class QskTextOptions;
class QSK_EXPORT QskCheckBox : public QskAbstractButton
{
Q_OBJECT
Q_PROPERTY( QString text READ text WRITE setText NOTIFY textChanged )
Q_PROPERTY( QskTextOptions textOptions READ textOptions
WRITE setTextOptions NOTIFY textOptionsChanged )
using Inherited = QskAbstractButton;
public:
QSK_SUBCONTROLS( Panel, Indicator )
QSK_SUBCONTROLS( Panel, IndicatorBox, IndicatorTic, Text)
QskCheckBox( QQuickItem* parent = nullptr );
~QskCheckBox() override;
bool isCheckable() const override final;
QString text() const;
QskTextOptions textOptions() const;
Q_SIGNALS:
void textChanged( const QString& );
void textOptionsChanged( const QskTextOptions& );
public Q_SLOTS:
void setText( const QString& );
void setTextOptions( const QskTextOptions& );
private:
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};
#endif

View File

@ -6,10 +6,14 @@
#include "QskCheckBoxSkinlet.h"
#include "QskCheckBox.h"
#include "QskSGNode.h"
#include "QskTextOptions.h"
#include <qfontmetrics.h>
#include <QSGFlatColorMaterial>
#include <qsgnode.h>
#include <algorithm>
namespace
{
class IndicatorNode : public QSGGeometryNode
@ -62,7 +66,7 @@ namespace
QskCheckBoxSkinlet::QskCheckBoxSkinlet( QskSkin* skin )
: QskSkinlet( skin )
{
setNodeRoles( { PanelRole, IndicatorRole } );
setNodeRoles( { PanelRole, TextRole, IndicatorBoxRole, IndicatorRole } );
}
QskCheckBoxSkinlet::~QskCheckBoxSkinlet()
@ -72,10 +76,26 @@ QskCheckBoxSkinlet::~QskCheckBoxSkinlet()
QRectF QskCheckBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
{
if ( subControl == QskCheckBox::Indicator )
return skinnable->innerBox( QskCheckBox::Panel, contentsRect );
const auto checkBox = static_cast< const QskCheckBox* >( skinnable );
return contentsRect;
if ( subControl == QskCheckBox::Panel)
{
return contentsRect;
}
else if ( subControl == QskCheckBox::Text)
{
return textRect(checkBox, contentsRect );
}
else if ( subControl == QskCheckBox::IndicatorTic )
{
return indicatorRect(checkBox, contentsRect );
}
else if ( subControl == QskCheckBox::IndicatorBox )
{
return indicatorBoxRect(checkBox, contentsRect );
}
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
QSGNode* QskCheckBoxSkinlet::updateSubNode(
@ -88,6 +108,12 @@ QSGNode* QskCheckBoxSkinlet::updateSubNode(
case PanelRole:
return updateBoxNode( skinnable, node, QskCheckBox::Panel );
case TextRole:
return updateTextNode( checkBox, node );
case IndicatorBoxRole:
return updateBoxNode( skinnable, node, QskCheckBox::IndicatorBox );
case IndicatorRole:
return updateIndicatorNode( checkBox, node );
}
@ -95,6 +121,64 @@ QSGNode* QskCheckBoxSkinlet::updateSubNode(
return Inherited::updateSubNode( skinnable, nodeRole, node );
}
QRectF QskCheckBoxSkinlet::textRect( const QskCheckBox* checkBox,
const QRectF& contentsRect ) const {
using Q = QskCheckBox;
QSizeF size;
const QFontMetricsF fm( checkBox->effectiveFont(Q::Text) );
if ( !checkBox->text().isEmpty() )
{
size += fm.size( Qt::TextShowMnemonic, checkBox->text() );
}
auto result = contentsRect;
result.setTopLeft( QPointF(result.right() - size.width() -
checkBox->marginHint( Q::Text ).right(),
result.y() + ( result.height() - size.height() ) / 2) );
return result;
}
QRectF QskCheckBoxSkinlet::indicatorRect( const QskCheckBox* checkBox,
const QRectF& contentsRect) const {
using Q = QskCheckBox;
auto rect = contentsRect;
auto size =
checkBox->strutSizeHint( Q::IndicatorTic ).grownBy(checkBox->marginHint( Q::IndicatorTic ) );
rect.setSize(size);
return rect;
}
QRectF QskCheckBoxSkinlet::indicatorBoxRect( const QskCheckBox* checkBox,
const QRectF& contentsRect ) const {
using Q = QskCheckBox;
auto rect = contentsRect;
auto size =
checkBox->strutSizeHint( Q::IndicatorBox ).grownBy(checkBox->marginHint(Q::IndicatorBox) );
rect.setSize(size);
return rect;
}
QSGNode* QskCheckBoxSkinlet::updateTextNode(
const QskCheckBox* checkBox, QSGNode* node ) const
{
using Q = QskCheckBox;
const auto rect = checkBox->subControlRect( Q::Text );
const auto textHeight = checkBox->effectiveFontHeight( Q::Text );
if ( !checkBox->clip() && ( rect.height() < textHeight ) )
return nullptr;
return QskSkinlet::updateTextNode( checkBox, node,
checkBox->text(), checkBox->textOptions(), Q::Text );
}
QSGNode* QskCheckBoxSkinlet::updateIndicatorNode(
const QskCheckBox* checkBox, QSGNode* node ) const
{
@ -103,12 +187,14 @@ QSGNode* QskCheckBoxSkinlet::updateIndicatorNode(
if ( checkBox->isChecked() == false )
return nullptr;
const auto rect = checkBox->subControlRect( Q::Indicator );
auto rect = checkBox->subControlRect(Q::IndicatorTic)
.marginsRemoved(checkBox->marginHint(Q::IndicatorTic) );
if ( rect.isEmpty() )
return nullptr;
auto indicatorNode = QskSGNode::ensureNode< IndicatorNode >( node );
indicatorNode->update( rect, checkBox->color( Q::Indicator ) );
indicatorNode->update( rect, checkBox->color( Q::IndicatorTic ) );
return indicatorNode;
}
@ -116,7 +202,31 @@ QSGNode* QskCheckBoxSkinlet::updateIndicatorNode(
QSizeF QskCheckBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint, const QSizeF& ) const
{
return skinnable->strutSizeHint( QskCheckBox::Panel );
using Q = QskCheckBox;
const auto checkBox = static_cast< const QskCheckBox* >( skinnable );
const QFontMetricsF fm( checkBox->effectiveFont(Q::Text) );
QSizeF sizeText;
if ( !checkBox->text().isEmpty() )
{
sizeText += fm.size( Qt::TextShowMnemonic, checkBox->text() )
.grownBy(checkBox->marginHint(Q::Text) );
}
auto sizeIndicator =
checkBox->strutSizeHint(Q::IndicatorTic).grownBy(checkBox->marginHint(Q::IndicatorTic) );
auto sizeIndicatorBox =
checkBox->strutSizeHint(Q::IndicatorBox).grownBy(checkBox->marginHint(Q::IndicatorBox) );
QSizeF size;
size.setWidth( sizeText.width() +
qMax( sizeIndicator.width(), sizeIndicatorBox.width() ) );
size.setHeight(std::max({ sizeIndicator.height(),
sizeIndicatorBox.height(),
sizeText.height() }) );
return size;
}
#include "moc_QskCheckBoxSkinlet.cpp"

View File

@ -20,6 +20,8 @@ class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet
enum NodeRole
{
PanelRole,
TextRole,
IndicatorBoxRole,
IndicatorRole,
RoleCount
@ -38,8 +40,14 @@ class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet
QSGNode* updateSubNode( const QskSkinnable*,
quint8 nodeRole, QSGNode* ) const override;
protected:
virtual QSGNode* updateTextNode( const QskCheckBox*, QSGNode* ) const;
virtual QSGNode* updateIndicatorNode( const QskCheckBox*, QSGNode* ) const;
private:
QRectF textRect( const QskCheckBox*, const QRectF& ) const;
QRectF indicatorRect( const QskCheckBox*, const QRectF& ) const;
QRectF indicatorBoxRect( const QskCheckBox*, const QRectF& ) const;
};
#endif