QskMenuSkinlet improved

This commit is contained in:
Uwe Rathmann 2021-12-28 15:33:13 +01:00
parent f1a324b216
commit 9fff09144a
4 changed files with 396 additions and 242 deletions

View File

@ -15,12 +15,12 @@
#include <qfontmetrics.h> #include <qfontmetrics.h>
template< class T > template< class T >
static T qskValueAt( const QskMenu* menu, int index ) static inline QVariant qskValueAt( const QskMenu* menu, int index )
{ {
const auto item = menu->itemAt( index ); const auto item = menu->itemAt( index );
if ( item.canConvert< T >() ) if ( item.canConvert< T >() )
return item.value< T >(); return item;
if ( item.canConvert< QVariantList >() ) if ( item.canConvert< QVariantList >() )
{ {
@ -28,234 +28,189 @@ static T qskValueAt( const QskMenu* menu, int index )
for ( const auto& value : list ) for ( const auto& value : list )
{ {
if ( value.canConvert< T >() ) if ( value.canConvert< T >() )
return value.value< T >(); return value;
} }
} }
return T(); return QVariant();
} }
static qreal qskMaxTextWidth( const QskMenu* menu ) class QskMenuSkinlet::PrivateData
{ {
const QFontMetricsF fm( menu->effectiveFont( QskMenu::Text ) ); public:
class CacheGuard
auto maxWidth = 0.0;
for ( int i = 0; i < menu->count(); i++ )
{ {
const auto value = menu->itemAt( i ); public:
CacheGuard( QskMenuSkinlet::PrivateData* data )
const auto text = qskValueAt< QString >( menu, i ); : m_data( data )
if( !text.isEmpty() )
{ {
const auto w = qskHorizontalAdvance( fm, text ); m_data->enableCache( true );
if( w > maxWidth )
maxWidth = w;
}
}
return maxWidth;
}
static qreal qskGraphicWidth( const QskMenu* menu )
{
const auto hint = menu->strutSizeHint( QskMenu::Graphic );
const qreal textHeight = menu->effectiveFontHeight( QskMenu::Text );
const auto h = qMax( hint.height(), textHeight );
qreal maxW = 0.0;
for ( int i = 0; i < menu->count(); i++ )
{
const auto graphic = qskValueAt< QskGraphic >( menu, i );
const auto w = graphic.widthForHeight( h );
if( w > maxW )
maxW = w;
}
return qMax( hint.width(), maxW );
}
static qreal qskCellWidth( const QskMenu* menu )
{
using Q = QskMenu;
const auto spacing = menu->spacingHint( Q::Cell );
const auto padding = menu->paddingHint( Q::Cell );
auto w = qskGraphicWidth( menu )
+ spacing + qskMaxTextWidth( menu );
w += padding.left() + padding.right();
const auto minWidth = menu->strutSizeHint( Q::Cell ).width();
return qMax( w, minWidth );
}
static qreal qskCellHeight( const QskMenu* menu )
{
using Q = QskMenu;
const auto graphicHeight = menu->strutSizeHint( Q::Graphic ).height();
const auto textHeight = menu->effectiveFontHeight( Q::Text );
const auto padding = menu->paddingHint( Q::Cell );
qreal h = qMax( graphicHeight, textHeight );
h += padding.top() + padding.bottom();
const auto minHeight = menu->strutSizeHint( Q::Cell ).height();
h = qMax( h, minHeight );
return h;
}
static QSGNode* qskUpdateGraphicNode( const QskMenu* menu,
const QRectF& rect, const QskGraphic& graphic, QSGNode* node )
{
const auto alignment = menu->alignmentHint( QskMenu::Graphic, Qt::AlignCenter );
const auto colorFilter = menu->effectiveGraphicFilter( QskMenu::Graphic );
return QskSkinlet::updateGraphicNode(
menu, node, graphic, colorFilter, rect, alignment );
}
static QSGNode* qskUpdateTextNode( const QskMenu* menu,
const QRectF& rect, const QString& text, QSGNode* node )
{
const auto alignment = menu->alignmentHint(
QskMenu::Text, Qt::AlignVCenter | Qt::AlignLeft );
return QskSkinlet::updateTextNode( menu, node, rect, alignment,
text, menu->textOptions(), QskMenu::Text );
}
static QSGNode* qskUpdateBackgroundNode( const QskMenu* menu, QSGNode* rootNode )
{
using Q = QskMenu;
const auto skinlet = menu->effectiveSkinlet();
auto node = rootNode ? rootNode->firstChild() : nullptr;
QSGNode* lastNode = nullptr;
for( int i = 0; i < menu->count(); i++ )
{
QSGNode* newNode = nullptr;
{
QskSkinStateChanger stateChanger( menu );
stateChanger.setStates(
skinlet->subControlCellStates( menu, Q::Cell, i ) );
newNode = QskSkinlet::updateBoxNode(
menu, node, menu->cellRect( i ), Q::Cell );
} }
if ( newNode ) ~CacheGuard()
{ {
if ( newNode == node ) m_data->enableCache( false );
}
private:
QskMenuSkinlet::PrivateData* m_data;
};
void enableCache( bool on )
{
m_isCaching = on;
m_cellHeight = m_cellWidth = m_graphicWidth = m_textWidth = -1.0;
}
inline qreal graphicWidth( const QskMenu* menu ) const
{
if ( m_isCaching )
{
if ( m_graphicWidth < 0.0 )
m_graphicWidth = graphicWidthInternal( menu );
return m_graphicWidth;
}
return graphicWidthInternal( menu );
}
inline qreal textWidth( const QskMenu* menu ) const
{
if ( m_isCaching )
{
if ( m_textWidth < 0.0 )
m_textWidth = textWidthInternal( menu );
return m_textWidth;
}
return textWidthInternal( menu );
}
inline qreal cellWidth( const QskMenu* menu ) const
{
if ( m_isCaching )
{
if ( m_cellWidth < 0.0 )
m_cellWidth = cellWidthInternal( menu );
return m_cellWidth;
}
return cellWidthInternal( menu );
}
inline qreal cellHeight( const QskMenu* menu ) const
{
if ( m_isCaching )
{
if ( m_cellHeight < 0.0 )
m_cellHeight = cellHeightInternal( menu );
return m_cellHeight;
}
return cellHeightInternal( menu );
}
private:
qreal graphicWidthInternal( const QskMenu* menu ) const
{
const auto skinlet = menu->effectiveSkinlet();
const auto hint = menu->strutSizeHint( QskMenu::Graphic );
const qreal textHeight = menu->effectiveFontHeight( QskMenu::Text );
const auto h = qMax( hint.height(), textHeight );
qreal maxW = 0.0;
for ( int i = 0; i < menu->count(); i++ )
{
const auto value = skinlet->valueAt( menu, QskMenu::Graphic, i );
if ( value.canConvert< QskGraphic >() )
{ {
node = node->nextSibling(); const auto graphic = value.value< QskGraphic >();
if ( !graphic.isNull() )
{
const auto w = graphic.widthForHeight( h );
if( w > maxW )
maxW = w;
}
} }
else }
return qMax( hint.width(), maxW );
}
qreal textWidthInternal( const QskMenu* menu ) const
{
const auto skinlet = menu->effectiveSkinlet();
const QFontMetricsF fm( menu->effectiveFont( QskMenu::Text ) );
auto maxWidth = 0.0;
for ( int i = 0; i < menu->count(); i++ )
{
const auto value = skinlet->valueAt( menu, QskMenu::Text, i );
if ( value.canConvert< QString >() )
{ {
if ( rootNode == nullptr ) const auto text = value.value< QString >();
rootNode = new QSGNode(); if( !text.isEmpty() )
{
if ( node ) const auto w = qskHorizontalAdvance( fm, text );
rootNode->insertChildNodeBefore( newNode, node ); if( w > maxWidth )
else maxWidth = w;
rootNode->appendChildNode( newNode ); }
} }
lastNode = newNode;
} }
return maxWidth;
} }
QskSGNode::removeAllChildNodesAfter( rootNode, lastNode ); qreal cellWidthInternal( const QskMenu* menu ) const
return rootNode;
}
static void qskUpdateItemNode(
const QskMenu* menu, const QRectF& graphicRect, const QskGraphic& graphic,
const QRectF& textRect, const QString& text, QSGNode* itemNode )
{
enum { GraphicRole, TextRole };
static QVector< quint8 > roles = { GraphicRole, TextRole };
for ( const auto role : roles )
{ {
auto oldNode = QskSGNode::findChildNode( itemNode, role ); using Q = QskMenu;
QSGNode* newNode = nullptr;
if( role == GraphicRole ) const auto spacing = menu->spacingHint( Q::Cell );
newNode = qskUpdateGraphicNode( menu, graphicRect, graphic, oldNode ); const auto padding = menu->paddingHint( Q::Cell );
else
newNode = qskUpdateTextNode( menu, textRect, text, oldNode );
QskSGNode::replaceChildNode( roles, role, itemNode, oldNode, newNode ); auto w = graphicWidth( menu ) + spacing + textWidth( menu );
w += padding.left() + padding.right();
const auto minWidth = menu->strutSizeHint( Q::Cell ).width();
return qMax( w, minWidth );
} }
}
static QSGNode* qskUpdateItemsNode( const QskMenu* menu, QSGNode* rootNode ) qreal cellHeightInternal( const QskMenu* menu ) const
{
using Q = QskMenu;
const auto skinlet = menu->effectiveSkinlet();
const auto spacing = menu->spacingHint( Q::Cell );
const auto graphicWidth = qskGraphicWidth( menu );
const auto contentsRect = menu->contentsRect();
if ( rootNode == nullptr )
rootNode = new QSGNode();
QSGNode* node = nullptr;
const auto count = skinlet->subControlCellCount( menu, Q::Cell );
for( int i = 0; i < count; i++ )
{ {
if ( node == nullptr ) using Q = QskMenu;
node = rootNode->firstChild();
else
node = node->nextSibling();
if ( node == nullptr ) const auto graphicHeight = menu->strutSizeHint( Q::Graphic ).height();
{ const auto textHeight = menu->effectiveFontHeight( Q::Text );
node = new QSGNode(); const auto padding = menu->paddingHint( Q::Cell );
rootNode->appendChildNode( node );
}
{ qreal h = qMax( graphicHeight, textHeight );
QskSkinStateChanger stateChanger( menu ); h += padding.top() + padding.bottom();
stateChanger.setStates(
skinlet->subControlCellStates( menu, Q::Cell, i ) );
const auto cellRect = skinlet->subControlCell( const auto minHeight = menu->strutSizeHint( Q::Cell ).height();
menu, contentsRect, Q::Cell, i ); h = qMax( h, minHeight );
auto graphicRect = cellRect; return h;
graphicRect.setWidth( graphicWidth );
auto textRect = cellRect;
textRect.setX( graphicRect.right() + spacing );
const auto graphic = qskValueAt< QskGraphic >( menu, i );
const auto text = qskValueAt< QString >( menu, i );
qskUpdateItemNode( menu, graphicRect, graphic,
textRect, text, node );
}
} }
QskSGNode::removeAllChildNodesAfter( rootNode, node ); bool m_isCaching;
return rootNode; mutable qreal m_graphicWidth = -1.0;
} mutable qreal m_textWidth = -1.0;
mutable qreal m_cellHeight = -1.0;
mutable qreal m_cellWidth = -1.0;
};
QskMenuSkinlet::QskMenuSkinlet( QskSkin* skin ) QskMenuSkinlet::QskMenuSkinlet( QskSkin* skin )
: Inherited( skin ) : Inherited( skin )
, m_data( new PrivateData() )
{ {
appendNodeRoles( { PanelRole } ); appendNodeRoles( { PanelRole } );
} }
@ -283,29 +238,62 @@ QRectF QskMenuSkinlet::subControlCell(
const QskSkinnable* skinnable, const QRectF& contentsRect, const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl, int index ) const QskAspect::Subcontrol subControl, int index ) const
{ {
// QskMenu::Text, QskMenu::Graphic ??? using Q = QskMenu;
if ( subControl == QskMenu::Cell )
const auto menu = static_cast< const QskMenu* >( skinnable );
if ( subControl == Q::Cell )
{ {
const auto menu = static_cast< const QskMenu* >( skinnable ); const auto r = menu->subControlContentsRect( Q::Panel );
const auto h = m_data->cellHeight( menu );
if ( index < 0 || index >= menu->count() )
return QRectF();
const auto r = menu->subControlContentsRect( QskMenu::Panel );
const auto h = qskCellHeight( menu );
return QRectF( r.x(), r.y() + index * h, r.width(), h ); return QRectF( r.x(), r.y() + index * h, r.width(), h );
} }
if ( subControl == QskMenu::Graphic || subControl == QskMenu::Text )
{
const auto r = subControlCell( menu, contentsRect, Q::Cell, index );
const auto graphicWidth = m_data->graphicWidth( menu );
if ( subControl == QskMenu::Graphic )
{
auto graphicRect = r;
graphicRect.setWidth( graphicWidth );
return QRectF( r.x(), r.y(), graphicWidth, r.height() );
}
else
{
auto textRect = r;
if ( graphicWidth > 0.0 )
{
const auto spacing = skinnable->spacingHint( Q::Cell );
textRect.setX( r.x() + graphicWidth + spacing );
}
return textRect;
}
}
return Inherited::subControlCell( return Inherited::subControlCell(
skinnable, contentsRect, subControl, index ); skinnable, contentsRect, subControl, index );
} }
int QskMenuSkinlet::subControlCellIndexAt(
const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl, const QPointF& pos ) const
{
const PrivateData::CacheGuard guard( m_data.get() );
return Inherited::subControlCellIndexAt( skinnable, contentsRect, subControl, pos );
}
int QskMenuSkinlet::subControlCellCount( int QskMenuSkinlet::subControlCellCount(
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) const const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) const
{ {
// QskMenu::Text, QskMenu::Graphic ??? using Q = QskMenu;
if ( subControl == QskMenu::Cell )
if ( subControl == Q::Cell || subControl == Q::Graphic || subControl == Q::Text )
{ {
const auto menu = static_cast< const QskMenu* >( skinnable ); const auto menu = static_cast< const QskMenu* >( skinnable );
return menu->count(); return menu->count();
@ -317,10 +305,11 @@ int QskMenuSkinlet::subControlCellCount(
QskAspect::States QskMenuSkinlet::subControlCellStates( QskAspect::States QskMenuSkinlet::subControlCellStates(
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index ) const const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index ) const
{ {
using Q = QskMenu;
auto states = Inherited::subControlCellStates( skinnable, subControl, index ); auto states = Inherited::subControlCellStates( skinnable, subControl, index );
// QskMenu::Text, QskMenu::Graphic ??? if ( subControl == Q::Cell || subControl == Q::Graphic || subControl == Q::Text )
if ( subControl == QskMenu::Cell )
{ {
const auto menu = static_cast< const QskMenu* >( skinnable ); const auto menu = static_cast< const QskMenu* >( skinnable );
if ( menu->currentIndex() == index ) if ( menu->currentIndex() == index )
@ -330,17 +319,38 @@ QskAspect::States QskMenuSkinlet::subControlCellStates(
return states; return states;
} }
QVariant QskMenuSkinlet::valueAt( const QskSkinnable* skinnable,
QskAspect::Subcontrol subControl, int index ) const
{
using Q = QskMenu;
const auto menu = static_cast< const QskMenu* >( skinnable );
if ( subControl == Q::Graphic )
return qskValueAt< QskGraphic >( menu, index );
if ( subControl == Q::Text )
return qskValueAt< QString >( menu, index );
return Inherited::valueAt( skinnable, subControl, index );
}
QSGNode* QskMenuSkinlet::updateContentsNode( QSGNode* QskMenuSkinlet::updateContentsNode(
const QskPopup* popup, QSGNode* contentsNode ) const const QskPopup* popup, QSGNode* contentsNode ) const
{ {
enum { Panel, Backgrounds, Cursor, Items }; const PrivateData::CacheGuard guard( m_data.get() );
static QVector< quint8 > roles = { Panel, Backgrounds, Cursor, Items }; return updateMenuNode( popup, contentsNode );
}
QSGNode* QskMenuSkinlet::updateMenuNode(
const QskSkinnable* skinnable, QSGNode* contentsNode ) const
{
enum { Panel, Background, Cursor, Graphic, Text };
static QVector< quint8 > roles = { Panel, Background, Cursor, Graphic, Text };
if ( contentsNode == nullptr ) if ( contentsNode == nullptr )
contentsNode = new QSGNode(); contentsNode = new QSGNode();
const auto menu = static_cast< const QskMenu* >( popup );
for ( const auto role : roles ) for ( const auto role : roles )
{ {
auto oldNode = QskSGNode::findChildNode( contentsNode, role ); auto oldNode = QskSGNode::findChildNode( contentsNode, role );
@ -351,22 +361,27 @@ QSGNode* QskMenuSkinlet::updateContentsNode(
{ {
case Panel: case Panel:
{ {
newNode = updateBoxNode( menu, oldNode, QskMenu::Panel ); newNode = updateBoxNode( skinnable, oldNode, QskMenu::Panel );
break; break;
} }
case Backgrounds: case Background:
{ {
newNode = qskUpdateBackgroundNode( menu, oldNode ); newNode = updateSeriesNode( skinnable, QskMenu::Cell, oldNode );
break; break;
} }
case Cursor: case Cursor:
{ {
newNode = updateBoxNode( menu, oldNode, QskMenu::Cursor ); newNode = updateBoxNode( skinnable, oldNode, QskMenu::Cursor );
break; break;
} }
case Items: case Graphic:
{ {
newNode = qskUpdateItemsNode( menu, oldNode ); newNode = updateSeriesNode( skinnable, QskMenu::Graphic, oldNode );
break;
}
case Text:
{
newNode = updateSeriesNode( skinnable, QskMenu::Text, oldNode );
break; break;
} }
} }
@ -377,18 +392,71 @@ QSGNode* QskMenuSkinlet::updateContentsNode(
return contentsNode; return contentsNode;
} }
QSGNode* QskMenuSkinlet::updateSeriesSubNode( const QskSkinnable* skinnable,
QskAspect::Subcontrol subControl, int index, QSGNode* node ) const
{
using Q = QskMenu;
auto menu = static_cast< const QskMenu* >( skinnable );
const auto rect = subControlCell( menu, menu->contentsRect(), subControl, index );
if ( subControl == Q::Cell )
{
return updateBoxNode( menu, node, rect, subControl );
}
if ( subControl == Q::Graphic )
{
const auto v = qskValueAt< QskGraphic >( menu, index );
const auto alignment = menu->alignmentHint( subControl, Qt::AlignCenter );
const auto filter = menu->effectiveGraphicFilter( subControl );
return QskSkinlet::updateGraphicNode(
menu, node, v.value< QskGraphic >(), filter, rect, alignment );
}
if ( subControl == Q::Text )
{
const auto v = qskValueAt< QString >( menu, index );
const auto alignment = menu->alignmentHint(
subControl, Qt::AlignVCenter | Qt::AlignLeft );
return QskSkinlet::updateTextNode( menu, node, rect, alignment,
v.value< QString>(), menu->textOptions(), QskMenu::Text );
}
return nullptr;
}
QSizeF QskMenuSkinlet::sizeHint( const QskSkinnable* skinnable, QSizeF QskMenuSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint which, const QSizeF& ) const Qt::SizeHint which, const QSizeF& ) const
{ {
if ( which != Qt::PreferredSize ) if ( which != Qt::PreferredSize )
return QSizeF(); return QSizeF();
const auto menu = static_cast< const QskMenu* >( skinnable ); const PrivateData::CacheGuard guard( m_data.get() );
const qreal w = qskCellWidth( menu ); const auto count = subControlCellCount( skinnable, QskMenu::Cell );
const auto h = menu->count() * qskCellHeight( menu );
return menu->outerBoxSize( QskMenu::Panel, QSizeF( w, h ) ); qreal w = 0.0;
qreal h = 0.0;
if ( count > 0 )
{
const auto menu = static_cast< const QskMenu* >( skinnable );
w = m_data->cellWidth( menu );
h = count * m_data->cellHeight( menu );
}
auto hint = skinnable->outerBoxSize( QskMenu::Panel, QSizeF( w, h ) );
hint = hint.expandedTo( skinnable->strutSizeHint( QskMenu::Panel ) );
return hint;
} }
#include "moc_QskMenuSkinlet.cpp" #include "moc_QskMenuSkinlet.cpp"

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <QskPopupSkinlet.h> #include <QskPopupSkinlet.h>
#include <memory>
class QskMenu; class QskMenu;
@ -26,14 +27,28 @@ class QSK_EXPORT QskMenuSkinlet : public QskPopupSkinlet
QRectF subControlCell( const QskSkinnable*, QRectF subControlCell( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol, int index ) const override; const QRectF&, QskAspect::Subcontrol, int index ) const override;
int subControlCellIndexAt( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol, const QPointF& ) const override;
int subControlCellCount( const QskSkinnable*, QskAspect::Subcontrol ) const override; int subControlCellCount( const QskSkinnable*, QskAspect::Subcontrol ) const override;
QskAspect::States subControlCellStates( const QskSkinnable*, QskAspect::States subControlCellStates( const QskSkinnable*,
QskAspect::Subcontrol, int index ) const override; QskAspect::Subcontrol, int index ) const override;
QVariant valueAt( const QskSkinnable*,
QskAspect::Subcontrol, int index ) const override;
QSizeF sizeHint( const QskSkinnable*, QSizeF sizeHint( const QskSkinnable*,
Qt::SizeHint, const QSizeF& ) const override; Qt::SizeHint, const QSizeF& ) const override;
private: protected:
QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const override; QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const override;
QSGNode* updateMenuNode( const QskSkinnable*, QSGNode* ) const;
QSGNode* updateSeriesSubNode( const QskSkinnable*,
QskAspect::Subcontrol, int index, QSGNode* ) const override;
private:
class PrivateData;
std::unique_ptr< PrivateData > m_data;
}; };

View File

@ -22,6 +22,7 @@
#include "QskTextColors.h" #include "QskTextColors.h"
#include "QskTextNode.h" #include "QskTextNode.h"
#include "QskTextOptions.h" #include "QskTextOptions.h"
#include "QskSkinStateChanger.h"
#include <qquickwindow.h> #include <qquickwindow.h>
#include <qsgsimplerectnode.h> #include <qsgsimplerectnode.h>
@ -563,24 +564,6 @@ 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;
}
int QskSkinlet::subControlCellIndexAt( const QskSkinnable* skinnable, int QskSkinlet::subControlCellIndexAt( const QskSkinnable* skinnable,
const QRectF& rect, QskAspect::Subcontrol subControl, const QPointF& pos ) const const QRectF& rect, QskAspect::Subcontrol subControl, const QPointF& pos ) const
{ {
@ -601,6 +584,60 @@ int QskSkinlet::subControlCellIndexAt( const QskSkinnable* skinnable,
return -1; return -1;
} }
QSGNode* QskSkinlet::updateSeriesNode( const QskSkinnable* skinnable,
QskAspect::Subcontrol subControl, QSGNode* rootNode ) const
{
auto node = rootNode ? rootNode->firstChild() : nullptr;
QSGNode* lastNode = nullptr;
const auto count = subControlCellCount( skinnable, subControl );
for( int i = 0; i < count; i++ )
{
QSGNode* newNode = nullptr;
{
const auto newStates = subControlCellStates( skinnable, subControl, i );
QskSkinStateChanger stateChanger( skinnable );
stateChanger.setStates( newStates );
newNode = updateSeriesSubNode( skinnable, subControl, i, node );
}
if ( newNode )
{
if ( newNode == node )
{
node = node->nextSibling();
}
else
{
if ( rootNode == nullptr )
rootNode = new QSGNode();
if ( node )
rootNode->insertChildNodeBefore( newNode, node );
else
rootNode->appendChildNode( newNode );
}
lastNode = newNode;
}
}
QskSGNode::removeAllChildNodesAfter( rootNode, lastNode );
return rootNode;
}
QSGNode* QskSkinlet::updateSeriesSubNode( const QskSkinnable*,
QskAspect::Subcontrol, int index, QSGNode* ) const
{
Q_UNUSED( index )
return nullptr;
}
QskAspect::States QskSkinlet::subControlCellStates( QskAspect::States QskSkinlet::subControlCellStates(
const QskSkinnable* skinnable, QskAspect::Subcontrol, int index ) const const QskSkinnable* skinnable, QskAspect::Subcontrol, int index ) const
{ {
@ -608,4 +645,29 @@ QskAspect::States QskSkinlet::subControlCellStates(
return skinnable->skinStates(); return skinnable->skinStates();
} }
QVariant QskSkinlet::valueAt( const QskSkinnable*,
QskAspect::Subcontrol, int index ) const
{
Q_UNUSED( index )
return QVariant();
}
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

@ -53,6 +53,9 @@ class QSK_EXPORT QskSkinlet
virtual QskAspect::States subControlCellStates( const QskSkinnable*, virtual QskAspect::States subControlCellStates( const QskSkinnable*,
QskAspect::Subcontrol, int index ) const; QskAspect::Subcontrol, int index ) const;
virtual QVariant valueAt( const QskSkinnable*,
QskAspect::Subcontrol, int index ) const;
const QVector< quint8 >& nodeRoles() const; const QVector< quint8 >& nodeRoles() const;
void setOwnedBySkinnable( bool on ); void setOwnedBySkinnable( bool on );
@ -130,6 +133,12 @@ class QSK_EXPORT QskSkinlet
const QskGraphic&, QskAspect::Subcontrol, const QskGraphic&, QskAspect::Subcontrol,
Qt::Orientations mirrored = Qt::Orientations() ) const; Qt::Orientations mirrored = Qt::Orientations() ) const;
QSGNode* updateSeriesNode( const QskSkinnable*,
QskAspect::Subcontrol, QSGNode* ) const;
virtual QSGNode* updateSeriesSubNode( const QskSkinnable*,
QskAspect::Subcontrol, int index, QSGNode* ) const;
void replaceChildNode( quint8 nodeRole, QSGNode* parentNode, void replaceChildNode( quint8 nodeRole, QSGNode* parentNode,
QSGNode* oldNode, QSGNode* newNode ) const; QSGNode* oldNode, QSGNode* newNode ) const;