QskMenuSkinlet improved
This commit is contained in:
parent
f1a324b216
commit
9fff09144a
@ -15,12 +15,12 @@
|
||||
#include <qfontmetrics.h>
|
||||
|
||||
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 );
|
||||
|
||||
if ( item.canConvert< T >() )
|
||||
return item.value< T >();
|
||||
return item;
|
||||
|
||||
if ( item.canConvert< QVariantList >() )
|
||||
{
|
||||
@ -28,37 +28,96 @@ static T qskValueAt( const QskMenu* menu, int index )
|
||||
for ( const auto& value : list )
|
||||
{
|
||||
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 ) );
|
||||
|
||||
auto maxWidth = 0.0;
|
||||
|
||||
for ( int i = 0; i < menu->count(); i++ )
|
||||
public:
|
||||
class CacheGuard
|
||||
{
|
||||
const auto value = menu->itemAt( i );
|
||||
|
||||
const auto text = qskValueAt< QString >( menu, i );
|
||||
if( !text.isEmpty() )
|
||||
public:
|
||||
CacheGuard( QskMenuSkinlet::PrivateData* data )
|
||||
: m_data( data )
|
||||
{
|
||||
const auto w = qskHorizontalAdvance( fm, text );
|
||||
if( w > maxWidth )
|
||||
maxWidth = w;
|
||||
}
|
||||
m_data->enableCache( true );
|
||||
}
|
||||
|
||||
return maxWidth;
|
||||
~CacheGuard()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static qreal qskGraphicWidth( const QskMenu* menu )
|
||||
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 );
|
||||
|
||||
@ -67,24 +126,56 @@ static qreal qskGraphicWidth( const QskMenu* menu )
|
||||
qreal maxW = 0.0;
|
||||
for ( int i = 0; i < menu->count(); i++ )
|
||||
{
|
||||
const auto graphic = qskValueAt< QskGraphic >( menu, i );
|
||||
const auto value = skinlet->valueAt( menu, QskMenu::Graphic, i );
|
||||
if ( value.canConvert< QskGraphic >() )
|
||||
{
|
||||
const auto graphic = value.value< QskGraphic >();
|
||||
if ( !graphic.isNull() )
|
||||
{
|
||||
const auto w = graphic.widthForHeight( h );
|
||||
if( w > maxW )
|
||||
maxW = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return qMax( hint.width(), maxW );
|
||||
}
|
||||
|
||||
static qreal qskCellWidth( const QskMenu* menu )
|
||||
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 >() )
|
||||
{
|
||||
const auto text = value.value< QString >();
|
||||
if( !text.isEmpty() )
|
||||
{
|
||||
const auto w = qskHorizontalAdvance( fm, text );
|
||||
if( w > maxWidth )
|
||||
maxWidth = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
qreal cellWidthInternal( const QskMenu* menu ) const
|
||||
{
|
||||
using Q = QskMenu;
|
||||
|
||||
const auto spacing = menu->spacingHint( Q::Cell );
|
||||
const auto padding = menu->paddingHint( Q::Cell );
|
||||
|
||||
auto w = qskGraphicWidth( menu )
|
||||
+ spacing + qskMaxTextWidth( menu );
|
||||
auto w = graphicWidth( menu ) + spacing + textWidth( menu );
|
||||
|
||||
w += padding.left() + padding.right();
|
||||
|
||||
@ -92,7 +183,7 @@ static qreal qskCellWidth( const QskMenu* menu )
|
||||
return qMax( w, minWidth );
|
||||
}
|
||||
|
||||
static qreal qskCellHeight( const QskMenu* menu )
|
||||
qreal cellHeightInternal( const QskMenu* menu ) const
|
||||
{
|
||||
using Q = QskMenu;
|
||||
|
||||
@ -109,153 +200,17 @@ static qreal qskCellHeight( const QskMenu* menu )
|
||||
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 );
|
||||
bool m_isCaching;
|
||||
|
||||
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 )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 );
|
||||
QSGNode* newNode = nullptr;
|
||||
|
||||
if( role == GraphicRole )
|
||||
newNode = qskUpdateGraphicNode( menu, graphicRect, graphic, oldNode );
|
||||
else
|
||||
newNode = qskUpdateTextNode( menu, textRect, text, oldNode );
|
||||
|
||||
QskSGNode::replaceChildNode( roles, role, itemNode, oldNode, newNode );
|
||||
}
|
||||
}
|
||||
|
||||
static QSGNode* qskUpdateItemsNode( const QskMenu* menu, QSGNode* rootNode )
|
||||
{
|
||||
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 )
|
||||
node = rootNode->firstChild();
|
||||
else
|
||||
node = node->nextSibling();
|
||||
|
||||
if ( node == nullptr )
|
||||
{
|
||||
node = new QSGNode();
|
||||
rootNode->appendChildNode( node );
|
||||
}
|
||||
|
||||
{
|
||||
QskSkinStateChanger stateChanger( menu );
|
||||
stateChanger.setStates(
|
||||
skinlet->subControlCellStates( menu, Q::Cell, i ) );
|
||||
|
||||
const auto cellRect = skinlet->subControlCell(
|
||||
menu, contentsRect, Q::Cell, i );
|
||||
|
||||
auto graphicRect = cellRect;
|
||||
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 );
|
||||
|
||||
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 )
|
||||
: Inherited( skin )
|
||||
, m_data( new PrivateData() )
|
||||
{
|
||||
appendNodeRoles( { PanelRole } );
|
||||
}
|
||||
@ -283,29 +238,62 @@ QRectF QskMenuSkinlet::subControlCell(
|
||||
const QskSkinnable* skinnable, const QRectF& contentsRect,
|
||||
QskAspect::Subcontrol subControl, int index ) const
|
||||
{
|
||||
// QskMenu::Text, QskMenu::Graphic ???
|
||||
if ( subControl == QskMenu::Cell )
|
||||
{
|
||||
using Q = QskMenu;
|
||||
|
||||
const auto menu = static_cast< const QskMenu* >( skinnable );
|
||||
|
||||
if ( index < 0 || index >= menu->count() )
|
||||
return QRectF();
|
||||
|
||||
const auto r = menu->subControlContentsRect( QskMenu::Panel );
|
||||
const auto h = qskCellHeight( menu );
|
||||
if ( subControl == Q::Cell )
|
||||
{
|
||||
const auto r = menu->subControlContentsRect( Q::Panel );
|
||||
const auto h = m_data->cellHeight( menu );
|
||||
|
||||
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(
|
||||
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(
|
||||
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) const
|
||||
{
|
||||
// QskMenu::Text, QskMenu::Graphic ???
|
||||
if ( subControl == QskMenu::Cell )
|
||||
using Q = QskMenu;
|
||||
|
||||
if ( subControl == Q::Cell || subControl == Q::Graphic || subControl == Q::Text )
|
||||
{
|
||||
const auto menu = static_cast< const QskMenu* >( skinnable );
|
||||
return menu->count();
|
||||
@ -317,10 +305,11 @@ int QskMenuSkinlet::subControlCellCount(
|
||||
QskAspect::States QskMenuSkinlet::subControlCellStates(
|
||||
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index ) const
|
||||
{
|
||||
using Q = QskMenu;
|
||||
|
||||
auto states = Inherited::subControlCellStates( skinnable, subControl, index );
|
||||
|
||||
// QskMenu::Text, QskMenu::Graphic ???
|
||||
if ( subControl == QskMenu::Cell )
|
||||
if ( subControl == Q::Cell || subControl == Q::Graphic || subControl == Q::Text )
|
||||
{
|
||||
const auto menu = static_cast< const QskMenu* >( skinnable );
|
||||
if ( menu->currentIndex() == index )
|
||||
@ -330,17 +319,38 @@ QskAspect::States QskMenuSkinlet::subControlCellStates(
|
||||
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(
|
||||
const QskPopup* popup, QSGNode* contentsNode ) const
|
||||
{
|
||||
enum { Panel, Backgrounds, Cursor, Items };
|
||||
static QVector< quint8 > roles = { Panel, Backgrounds, Cursor, Items };
|
||||
const PrivateData::CacheGuard guard( m_data.get() );
|
||||
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 )
|
||||
contentsNode = new QSGNode();
|
||||
|
||||
const auto menu = static_cast< const QskMenu* >( popup );
|
||||
|
||||
for ( const auto role : roles )
|
||||
{
|
||||
auto oldNode = QskSGNode::findChildNode( contentsNode, role );
|
||||
@ -351,22 +361,27 @@ QSGNode* QskMenuSkinlet::updateContentsNode(
|
||||
{
|
||||
case Panel:
|
||||
{
|
||||
newNode = updateBoxNode( menu, oldNode, QskMenu::Panel );
|
||||
newNode = updateBoxNode( skinnable, oldNode, QskMenu::Panel );
|
||||
break;
|
||||
}
|
||||
case Backgrounds:
|
||||
case Background:
|
||||
{
|
||||
newNode = qskUpdateBackgroundNode( menu, oldNode );
|
||||
newNode = updateSeriesNode( skinnable, QskMenu::Cell, oldNode );
|
||||
break;
|
||||
}
|
||||
case Cursor:
|
||||
{
|
||||
newNode = updateBoxNode( menu, oldNode, QskMenu::Cursor );
|
||||
newNode = updateBoxNode( skinnable, oldNode, QskMenu::Cursor );
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -377,18 +392,71 @@ QSGNode* QskMenuSkinlet::updateContentsNode(
|
||||
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,
|
||||
Qt::SizeHint which, const QSizeF& ) const
|
||||
{
|
||||
if ( which != Qt::PreferredSize )
|
||||
return QSizeF();
|
||||
|
||||
const PrivateData::CacheGuard guard( m_data.get() );
|
||||
|
||||
const auto count = subControlCellCount( skinnable, QskMenu::Cell );
|
||||
|
||||
qreal w = 0.0;
|
||||
qreal h = 0.0;
|
||||
|
||||
if ( count > 0 )
|
||||
{
|
||||
const auto menu = static_cast< const QskMenu* >( skinnable );
|
||||
|
||||
const qreal w = qskCellWidth( menu );
|
||||
const auto h = menu->count() * qskCellHeight( menu );
|
||||
w = m_data->cellWidth( menu );
|
||||
h = count * m_data->cellHeight( menu );
|
||||
}
|
||||
|
||||
return menu->outerBoxSize( QskMenu::Panel, QSizeF( w, h ) );
|
||||
auto hint = skinnable->outerBoxSize( QskMenu::Panel, QSizeF( w, h ) );
|
||||
hint = hint.expandedTo( skinnable->strutSizeHint( QskMenu::Panel ) );
|
||||
|
||||
return hint;
|
||||
}
|
||||
|
||||
#include "moc_QskMenuSkinlet.cpp"
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <QskPopupSkinlet.h>
|
||||
#include <memory>
|
||||
|
||||
class QskMenu;
|
||||
|
||||
@ -26,14 +27,28 @@ class QSK_EXPORT QskMenuSkinlet : public QskPopupSkinlet
|
||||
QRectF subControlCell( const QskSkinnable*,
|
||||
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;
|
||||
|
||||
QskAspect::States subControlCellStates( const QskSkinnable*,
|
||||
QskAspect::Subcontrol, int index ) const override;
|
||||
|
||||
QVariant valueAt( const QskSkinnable*,
|
||||
QskAspect::Subcontrol, int index ) const override;
|
||||
|
||||
QSizeF sizeHint( const QskSkinnable*,
|
||||
Qt::SizeHint, const QSizeF& ) const override;
|
||||
|
||||
private:
|
||||
protected:
|
||||
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;
|
||||
};
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "QskTextColors.h"
|
||||
#include "QskTextNode.h"
|
||||
#include "QskTextOptions.h"
|
||||
#include "QskSkinStateChanger.h"
|
||||
|
||||
#include <qquickwindow.h>
|
||||
#include <qsgsimplerectnode.h>
|
||||
@ -563,24 +564,6 @@ 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;
|
||||
}
|
||||
|
||||
int QskSkinlet::subControlCellIndexAt( const QskSkinnable* skinnable,
|
||||
const QRectF& rect, QskAspect::Subcontrol subControl, const QPointF& pos ) const
|
||||
{
|
||||
@ -601,6 +584,60 @@ int QskSkinlet::subControlCellIndexAt( const QskSkinnable* skinnable,
|
||||
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(
|
||||
const QskSkinnable* skinnable, QskAspect::Subcontrol, int index ) const
|
||||
{
|
||||
@ -608,4 +645,29 @@ QskAspect::States QskSkinlet::subControlCellStates(
|
||||
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"
|
||||
|
@ -53,6 +53,9 @@ class QSK_EXPORT QskSkinlet
|
||||
virtual QskAspect::States subControlCellStates( const QskSkinnable*,
|
||||
QskAspect::Subcontrol, int index ) const;
|
||||
|
||||
virtual QVariant valueAt( const QskSkinnable*,
|
||||
QskAspect::Subcontrol, int index ) const;
|
||||
|
||||
const QVector< quint8 >& nodeRoles() const;
|
||||
|
||||
void setOwnedBySkinnable( bool on );
|
||||
@ -130,6 +133,12 @@ class QSK_EXPORT QskSkinlet
|
||||
const QskGraphic&, QskAspect::Subcontrol,
|
||||
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,
|
||||
QSGNode* oldNode, QSGNode* newNode ) const;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user