QskGraphicLabel::panel property added

This commit is contained in:
Uwe Rathmann 2021-08-26 15:17:41 +02:00
parent bd0c40b241
commit 26710da0b3
8 changed files with 130 additions and 26 deletions

View File

@ -11,6 +11,7 @@
#include "QskSetup.h"
#include "QskSkin.h"
QSK_SUBCONTROL( QskGraphicLabel, Panel )
QSK_SUBCONTROL( QskGraphicLabel, Graphic )
class QskGraphicLabel::PrivateData
@ -22,6 +23,7 @@ class QskGraphicLabel::PrivateData
, fillMode( QskGraphicLabel::PreserveAspectFit )
, mirror( false )
, isSourceDirty( !sourceUrl.isEmpty() )
, hasPanel( false )
{
}
@ -33,6 +35,7 @@ class QskGraphicLabel::PrivateData
uint fillMode : 2;
bool mirror : 1;
bool isSourceDirty : 1;
bool hasPanel : 1;
};
QskGraphicLabel::QskGraphicLabel( const QUrl& source, QQuickItem* parent )
@ -65,6 +68,24 @@ QskGraphicLabel::~QskGraphicLabel()
{
}
void QskGraphicLabel::setPanel( bool on )
{
if ( on == m_data->hasPanel )
return;
m_data->hasPanel = on;
resetImplicitSize();
update();
Q_EMIT panelChanged( on );
}
bool QskGraphicLabel::hasPanel() const
{
return m_data->hasPanel;
}
bool QskGraphicLabel::isEmpty() const
{
return m_data->graphic.isNull() && m_data->source.isEmpty();

View File

@ -31,10 +31,13 @@ class QSK_EXPORT QskGraphicLabel : public QskControl
Q_PROPERTY( FillMode fillMode READ fillMode
WRITE setFillMode NOTIFY fillModeChanged )
Q_PROPERTY( bool panel READ hasPanel
WRITE setPanel NOTIFY panelChanged )
using Inherited = QskControl;
public:
QSK_SUBCONTROLS( Graphic )
QSK_SUBCONTROLS( Panel, Graphic )
enum FillMode
{
@ -84,6 +87,9 @@ class QSK_EXPORT QskGraphicLabel : public QskControl
void resetGraphicRole();
int graphicRole() const;
void setPanel( bool );
bool hasPanel() const;
Q_SIGNALS:
void sourceChanged();
void mirrorChanged();
@ -91,6 +97,7 @@ class QSK_EXPORT QskGraphicLabel : public QskControl
void graphicRoleChanged( int );
void alignmentChanged( Qt::Alignment );
void fillModeChanged( FillMode );
void panelChanged( bool );
public Q_SLOTS:
void setGraphic( const QskGraphic& );

View File

@ -15,7 +15,7 @@
QskGraphicLabelSkinlet::QskGraphicLabelSkinlet( QskSkin* skin )
: Inherited( skin )
{
setNodeRoles( { GraphicRole } );
setNodeRoles( { PanelRole, GraphicRole } );
}
QskGraphicLabelSkinlet::~QskGraphicLabelSkinlet() = default;
@ -23,11 +23,23 @@ QskGraphicLabelSkinlet::~QskGraphicLabelSkinlet() = default;
QRectF QskGraphicLabelSkinlet::subControlRect( const QskSkinnable* skinnable,
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
{
const auto label = static_cast< const QskGraphicLabel* >( skinnable );
if ( subControl == QskGraphicLabel::Graphic )
if ( subControl == QskGraphicLabel::Panel )
{
return graphicRect( label, contentsRect );
return contentsRect;
}
else if ( subControl == QskGraphicLabel::Graphic )
{
auto innerRect = contentsRect;
const auto label = static_cast< const QskGraphicLabel* >( skinnable );
if ( label->hasPanel() )
{
innerRect = label->subControlContentsRect(
innerRect, QskGraphicLabel::Panel );
}
return graphicRect( label, innerRect );
}
return Inherited::subControlRect( skinnable, contentsRect, subControl );
@ -40,6 +52,13 @@ QSGNode* QskGraphicLabelSkinlet::updateSubNode(
switch ( nodeRole )
{
case PanelRole:
{
if ( !label->hasPanel() )
return nullptr;
return updateBoxNode( label, node, QskGraphicLabel::Panel );
}
case GraphicRole:
{
return updateGraphicNode( label, node );
@ -52,6 +71,8 @@ QSGNode* QskGraphicLabelSkinlet::updateSubNode(
QRect QskGraphicLabelSkinlet::graphicRect(
const QskGraphicLabel* label, const QRectF& contentsRect ) const
{
using Q = QskGraphicLabel;
// textures are in integers, to avoid useless recalculations
// that finally will be rounded anyway, we calculate in integers
@ -59,18 +80,18 @@ QRect QskGraphicLabelSkinlet::graphicRect(
const QRect graphicRect = contentsRect.toAlignedRect();
if ( fillMode == QskGraphicLabel::Stretch )
if ( fillMode == Q::Stretch )
{
return graphicRect;
}
QSizeF sz = label->effectiveSourceSize();
if ( fillMode == QskGraphicLabel::PreserveAspectFit )
if ( fillMode == Q::PreserveAspectFit )
{
sz.scale( graphicRect.size(), Qt::KeepAspectRatio );
}
else if ( fillMode == QskGraphicLabel::PreserveAspectCrop )
else if ( fillMode == Q::PreserveAspectCrop )
{
sz.scale( graphicRect.size(), Qt::KeepAspectRatioByExpanding );
}
@ -82,14 +103,16 @@ QRect QskGraphicLabelSkinlet::graphicRect(
QSGNode* QskGraphicLabelSkinlet::updateGraphicNode(
const QskGraphicLabel* label, QSGNode* node ) const
{
using Q = QskGraphicLabel;
const auto colorFilter = label->graphicFilter();
const auto rect = label->subControlRect( QskGraphicLabel::Graphic );
const auto rect = label->subControlRect( Q::Graphic );
Qt::Orientations mirrored;
if ( label->mirror() )
mirrored = Qt::Horizontal;
if ( label->fillMode() == QskGraphicLabel::Stretch )
if ( label->fillMode() == Q::Stretch )
{
node = QskSkinlet::updateGraphicNode( label, node,
label->graphic(), colorFilter, rect, mirrored );
@ -106,28 +129,57 @@ QSGNode* QskGraphicLabelSkinlet::updateGraphicNode(
QSizeF QskGraphicLabelSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint which, const QSizeF& constraint ) const
{
using Q = QskGraphicLabel;
if ( which != Qt::PreferredSize )
return QSizeF();
const bool hasConstraint =
( constraint.width() >= 0.0 ) || ( constraint.height() >= 0.0 );
const auto label = static_cast< const QskGraphicLabel* >( skinnable );
const auto sourceSize = label->effectiveSourceSize();
auto sz = label->effectiveSourceSize();
auto hint = sourceSize;
if ( !sz.isEmpty() )
if ( hasConstraint && !sourceSize.isEmpty() )
{
auto innerConstraint = constraint;
if ( label->hasPanel() )
{
constexpr qreal max = std::numeric_limits< int >::max();
QRectF r( 0.0, 0.0, max, max );
if ( constraint.width() >= 0.0 )
r.setWidth( constraint.width() );
else
r.setHeight( constraint.height() );
innerConstraint = label->subControlContentsRect( r, Q::Panel ).size();
}
const qreal aspectRatio = sourceSize.width() / sourceSize.height();
if ( constraint.width() >= 0.0 )
{
sz.setHeight( sz.height() * constraint.width() / sz.width() );
sz.setWidth( -1.0 );
}
else if ( constraint.height() >= 0.0 )
{
sz.setWidth( sz.width() * constraint.height() / sz.height() );
sz.setHeight( -1.0 );
}
hint.setHeight( innerConstraint.width() / aspectRatio );
else
hint.setWidth( innerConstraint.height() * aspectRatio );
}
return sz;
hint = hint.expandedTo( label->strutSizeHint( Q::Graphic ) );
if ( label->hasPanel() )
{
hint = label->outerBoxSize( Q::Panel, hint );
hint = hint.expandedTo( label->strutSizeHint( Q::Panel ) );
}
if ( hasConstraint )
hint = hintWithoutConstraint( hint, constraint );
return hint;
}
#include "moc_QskGraphicLabelSkinlet.cpp"

View File

@ -19,7 +19,7 @@ class QSK_EXPORT QskGraphicLabelSkinlet : public QskSkinlet
public:
enum NodeRole
{
GraphicRole
PanelRole, GraphicRole
};
Q_INVOKABLE QskGraphicLabelSkinlet( QskSkin* = nullptr );

View File

@ -448,4 +448,22 @@ QSGNode* QskSkinlet::updateGraphicNode(
return qskUpdateGraphicNode( skinnable, node, graphic, colorFilter, rect, mirrored );
}
QSizeF QskSkinlet::hintWithoutConstraint(
const QSizeF& hint, const QSizeF& constraint ) const
{
/*
This method is useful in situations, where a hint has been calculated
from a constraint and we want to return the calculated part only
*/
QSizeF h;
if ( constraint.width() < 0.0 )
h.setWidth( hint.width() );
if ( constraint.height() < 0.0 )
h.setHeight( hint.height() );
return h;
}
#include "moc_QskSkinlet.cpp"

View File

@ -98,6 +98,9 @@ class QSK_EXPORT QskSkinlet
void replaceChildNode( quint8 nodeRole, QSGNode* parentNode,
QSGNode* oldNode, QSGNode* newNode ) const;
QSizeF hintWithoutConstraint(
const QSizeF& hint, const QSizeF& constraint ) const;
private:
class PrivateData;
std::unique_ptr< PrivateData > m_data;

View File

@ -30,7 +30,7 @@ class QSK_EXPORT QskTextLabel : public QskControl
WRITE setAlignment NOTIFY alignmentChanged )
Q_PROPERTY( bool panel READ hasPanel
WRITE setPanel NOTIFY panelChanged FINAL )
WRITE setPanel NOTIFY panelChanged )
using Inherited = QskControl;

View File

@ -32,7 +32,10 @@ QRectF QskTextLabelSkinlet::subControlRect( const QskSkinnable* skinnable,
const auto label = static_cast< const QskTextLabel* >( skinnable );
if ( label->hasPanel() )
return label->subControlContentsRect( contentsRect, QskTextLabel::Panel );
{
return label->subControlContentsRect(
contentsRect, QskTextLabel::Panel );
}
return contentsRect;
}