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 "QskSetup.h"
#include "QskSkin.h" #include "QskSkin.h"
QSK_SUBCONTROL( QskGraphicLabel, Panel )
QSK_SUBCONTROL( QskGraphicLabel, Graphic ) QSK_SUBCONTROL( QskGraphicLabel, Graphic )
class QskGraphicLabel::PrivateData class QskGraphicLabel::PrivateData
@ -22,6 +23,7 @@ class QskGraphicLabel::PrivateData
, fillMode( QskGraphicLabel::PreserveAspectFit ) , fillMode( QskGraphicLabel::PreserveAspectFit )
, mirror( false ) , mirror( false )
, isSourceDirty( !sourceUrl.isEmpty() ) , isSourceDirty( !sourceUrl.isEmpty() )
, hasPanel( false )
{ {
} }
@ -33,6 +35,7 @@ class QskGraphicLabel::PrivateData
uint fillMode : 2; uint fillMode : 2;
bool mirror : 1; bool mirror : 1;
bool isSourceDirty : 1; bool isSourceDirty : 1;
bool hasPanel : 1;
}; };
QskGraphicLabel::QskGraphicLabel( const QUrl& source, QQuickItem* parent ) 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 bool QskGraphicLabel::isEmpty() const
{ {
return m_data->graphic.isNull() && m_data->source.isEmpty(); 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 Q_PROPERTY( FillMode fillMode READ fillMode
WRITE setFillMode NOTIFY fillModeChanged ) WRITE setFillMode NOTIFY fillModeChanged )
Q_PROPERTY( bool panel READ hasPanel
WRITE setPanel NOTIFY panelChanged )
using Inherited = QskControl; using Inherited = QskControl;
public: public:
QSK_SUBCONTROLS( Graphic ) QSK_SUBCONTROLS( Panel, Graphic )
enum FillMode enum FillMode
{ {
@ -84,6 +87,9 @@ class QSK_EXPORT QskGraphicLabel : public QskControl
void resetGraphicRole(); void resetGraphicRole();
int graphicRole() const; int graphicRole() const;
void setPanel( bool );
bool hasPanel() const;
Q_SIGNALS: Q_SIGNALS:
void sourceChanged(); void sourceChanged();
void mirrorChanged(); void mirrorChanged();
@ -91,6 +97,7 @@ class QSK_EXPORT QskGraphicLabel : public QskControl
void graphicRoleChanged( int ); void graphicRoleChanged( int );
void alignmentChanged( Qt::Alignment ); void alignmentChanged( Qt::Alignment );
void fillModeChanged( FillMode ); void fillModeChanged( FillMode );
void panelChanged( bool );
public Q_SLOTS: public Q_SLOTS:
void setGraphic( const QskGraphic& ); void setGraphic( const QskGraphic& );

View File

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

View File

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

View File

@ -448,4 +448,22 @@ QSGNode* QskSkinlet::updateGraphicNode(
return qskUpdateGraphicNode( skinnable, node, graphic, colorFilter, rect, mirrored ); 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" #include "moc_QskSkinlet.cpp"

View File

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

View File

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

View File

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