introducing series/sample for subcontrols being related to multiple

instances
This commit is contained in:
Uwe Rathmann 2021-12-28 16:14:30 +01:00
parent 9fff09144a
commit aca538a89d
5 changed files with 74 additions and 60 deletions

View File

@ -308,13 +308,13 @@ void QskMenu::setSelectedIndex( int index )
QRectF QskMenu::cellRect( int index ) const QRectF QskMenu::cellRect( int index ) const
{ {
return effectiveSkinlet()->subControlCell( return effectiveSkinlet()->sampleRect(
this, contentsRect(), QskMenu::Cell, index ); this, contentsRect(), QskMenu::Cell, index );
} }
int QskMenu::indexAtPosition( const QPointF& pos ) const int QskMenu::indexAtPosition( const QPointF& pos ) const
{ {
return effectiveSkinlet()->subControlCellIndexAt( return effectiveSkinlet()->sampleIndexAt(
this, contentsRect(), QskMenu::Cell, pos ); this, contentsRect(), QskMenu::Cell, pos );
} }

View File

@ -15,7 +15,7 @@
#include <qfontmetrics.h> #include <qfontmetrics.h>
template< class T > template< class T >
static inline QVariant qskValueAt( const QskMenu* menu, int index ) static inline QVariant qskSampleAt( const QskMenu* menu, int index )
{ {
const auto item = menu->itemAt( index ); const auto item = menu->itemAt( index );
@ -35,6 +35,13 @@ static inline QVariant qskValueAt( const QskMenu* menu, int index )
return QVariant(); return QVariant();
} }
template< class T >
static inline T qskValueAt( const QskMenu* menu, int index )
{
const auto sample = qskSampleAt< T >( menu, index );
return sample.template value< T >();
}
class QskMenuSkinlet::PrivateData class QskMenuSkinlet::PrivateData
{ {
public: public:
@ -126,10 +133,10 @@ class QskMenuSkinlet::PrivateData
qreal maxW = 0.0; qreal maxW = 0.0;
for ( int i = 0; i < menu->count(); i++ ) for ( int i = 0; i < menu->count(); i++ )
{ {
const auto value = skinlet->valueAt( menu, QskMenu::Graphic, i ); const auto sample = skinlet->sampleAt( menu, QskMenu::Graphic, i );
if ( value.canConvert< QskGraphic >() ) if ( sample.canConvert< QskGraphic >() )
{ {
const auto graphic = value.value< QskGraphic >(); const auto graphic = sample.value< QskGraphic >();
if ( !graphic.isNull() ) if ( !graphic.isNull() )
{ {
const auto w = graphic.widthForHeight( h ); const auto w = graphic.widthForHeight( h );
@ -152,10 +159,10 @@ class QskMenuSkinlet::PrivateData
for ( int i = 0; i < menu->count(); i++ ) for ( int i = 0; i < menu->count(); i++ )
{ {
const auto value = skinlet->valueAt( menu, QskMenu::Text, i ); const auto sample = skinlet->sampleAt( menu, QskMenu::Text, i );
if ( value.canConvert< QString >() ) if ( sample.canConvert< QString >() )
{ {
const auto text = value.value< QString >(); const auto text = sample.value< QString >();
if( !text.isEmpty() ) if( !text.isEmpty() )
{ {
const auto w = qskHorizontalAdvance( fm, text ); const auto w = qskHorizontalAdvance( fm, text );
@ -234,7 +241,7 @@ QRectF QskMenuSkinlet::subControlRect(
return Inherited::subControlRect( skinnable, contentsRect, subControl ); return Inherited::subControlRect( skinnable, contentsRect, subControl );
} }
QRectF QskMenuSkinlet::subControlCell( QRectF QskMenuSkinlet::sampleRect(
const QskSkinnable* skinnable, const QRectF& contentsRect, const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl, int index ) const QskAspect::Subcontrol subControl, int index ) const
{ {
@ -252,7 +259,7 @@ QRectF QskMenuSkinlet::subControlCell(
if ( subControl == QskMenu::Graphic || subControl == QskMenu::Text ) if ( subControl == QskMenu::Graphic || subControl == QskMenu::Text )
{ {
const auto r = subControlCell( menu, contentsRect, Q::Cell, index ); const auto r = sampleRect( menu, contentsRect, Q::Cell, index );
const auto graphicWidth = m_data->graphicWidth( menu ); const auto graphicWidth = m_data->graphicWidth( menu );
if ( subControl == QskMenu::Graphic ) if ( subControl == QskMenu::Graphic )
@ -276,19 +283,19 @@ QRectF QskMenuSkinlet::subControlCell(
} }
} }
return Inherited::subControlCell( return Inherited::sampleRect(
skinnable, contentsRect, subControl, index ); skinnable, contentsRect, subControl, index );
} }
int QskMenuSkinlet::subControlCellIndexAt( int QskMenuSkinlet::sampleIndexAt(
const QskSkinnable* skinnable, const QRectF& contentsRect, const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl, const QPointF& pos ) const QskAspect::Subcontrol subControl, const QPointF& pos ) const
{ {
const PrivateData::CacheGuard guard( m_data.get() ); const PrivateData::CacheGuard guard( m_data.get() );
return Inherited::subControlCellIndexAt( skinnable, contentsRect, subControl, pos ); return Inherited::sampleIndexAt( skinnable, contentsRect, subControl, pos );
} }
int QskMenuSkinlet::subControlCellCount( int QskMenuSkinlet::sampleCount(
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) const const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) const
{ {
using Q = QskMenu; using Q = QskMenu;
@ -299,15 +306,15 @@ int QskMenuSkinlet::subControlCellCount(
return menu->count(); return menu->count();
} }
return Inherited::subControlCellCount( skinnable, subControl ); return Inherited::sampleCount( skinnable, subControl );
} }
QskAspect::States QskMenuSkinlet::subControlCellStates( QskAspect::States QskMenuSkinlet::sampleStates(
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index ) const const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index ) const
{ {
using Q = QskMenu; using Q = QskMenu;
auto states = Inherited::subControlCellStates( skinnable, subControl, index ); auto states = Inherited::sampleStates( skinnable, subControl, index );
if ( subControl == Q::Cell || subControl == Q::Graphic || subControl == Q::Text ) if ( subControl == Q::Cell || subControl == Q::Graphic || subControl == Q::Text )
{ {
@ -319,7 +326,7 @@ QskAspect::States QskMenuSkinlet::subControlCellStates(
return states; return states;
} }
QVariant QskMenuSkinlet::valueAt( const QskSkinnable* skinnable, QVariant QskMenuSkinlet::sampleAt( const QskSkinnable* skinnable,
QskAspect::Subcontrol subControl, int index ) const QskAspect::Subcontrol subControl, int index ) const
{ {
using Q = QskMenu; using Q = QskMenu;
@ -327,12 +334,12 @@ QVariant QskMenuSkinlet::valueAt( const QskSkinnable* skinnable,
const auto menu = static_cast< const QskMenu* >( skinnable ); const auto menu = static_cast< const QskMenu* >( skinnable );
if ( subControl == Q::Graphic ) if ( subControl == Q::Graphic )
return qskValueAt< QskGraphic >( menu, index ); return qskSampleAt< QskGraphic >( menu, index );
if ( subControl == Q::Text ) if ( subControl == Q::Text )
return qskValueAt< QString >( menu, index ); return qskSampleAt< QString >( menu, index );
return Inherited::valueAt( skinnable, subControl, index ); return Inherited::sampleAt( skinnable, subControl, index );
} }
QSGNode* QskMenuSkinlet::updateContentsNode( QSGNode* QskMenuSkinlet::updateContentsNode(
@ -392,14 +399,14 @@ QSGNode* QskMenuSkinlet::updateMenuNode(
return contentsNode; return contentsNode;
} }
QSGNode* QskMenuSkinlet::updateSeriesSubNode( const QskSkinnable* skinnable, QSGNode* QskMenuSkinlet::updateSampleNode( const QskSkinnable* skinnable,
QskAspect::Subcontrol subControl, int index, QSGNode* node ) const QskAspect::Subcontrol subControl, int index, QSGNode* node ) const
{ {
using Q = QskMenu; using Q = QskMenu;
auto menu = static_cast< const QskMenu* >( skinnable ); auto menu = static_cast< const QskMenu* >( skinnable );
const auto rect = subControlCell( menu, menu->contentsRect(), subControl, index ); const auto rect = sampleRect( menu, menu->contentsRect(), subControl, index );
if ( subControl == Q::Cell ) if ( subControl == Q::Cell )
{ {
@ -408,24 +415,28 @@ QSGNode* QskMenuSkinlet::updateSeriesSubNode( const QskSkinnable* skinnable,
if ( subControl == Q::Graphic ) if ( subControl == Q::Graphic )
{ {
const auto v = qskValueAt< QskGraphic >( menu, index ); const auto graphic = qskValueAt< QskGraphic >( menu, index );
if ( graphic.isNull() )
return nullptr;
const auto alignment = menu->alignmentHint( subControl, Qt::AlignCenter ); const auto alignment = menu->alignmentHint( subControl, Qt::AlignCenter );
const auto filter = menu->effectiveGraphicFilter( subControl ); const auto filter = menu->effectiveGraphicFilter( subControl );
return QskSkinlet::updateGraphicNode( return QskSkinlet::updateGraphicNode(
menu, node, v.value< QskGraphic >(), filter, rect, alignment ); menu, node, graphic, filter, rect, alignment );
} }
if ( subControl == Q::Text ) if ( subControl == Q::Text )
{ {
const auto v = qskValueAt< QString >( menu, index ); const auto text = qskValueAt< QString >( menu, index );
if ( text.isEmpty() )
return nullptr;
const auto alignment = menu->alignmentHint( const auto alignment = menu->alignmentHint(
subControl, Qt::AlignVCenter | Qt::AlignLeft ); subControl, Qt::AlignVCenter | Qt::AlignLeft );
return QskSkinlet::updateTextNode( menu, node, rect, alignment, return QskSkinlet::updateTextNode( menu, node, rect, alignment,
v.value< QString>(), menu->textOptions(), QskMenu::Text ); text, menu->textOptions(), QskMenu::Text );
} }
return nullptr; return nullptr;
@ -440,7 +451,7 @@ QSizeF QskMenuSkinlet::sizeHint( const QskSkinnable* skinnable,
const PrivateData::CacheGuard guard( m_data.get() ); const PrivateData::CacheGuard guard( m_data.get() );
const auto count = subControlCellCount( skinnable, QskMenu::Cell ); const auto count = sampleCount( skinnable, QskMenu::Cell );
qreal w = 0.0; qreal w = 0.0;
qreal h = 0.0; qreal h = 0.0;

View File

@ -24,18 +24,18 @@ class QSK_EXPORT QskMenuSkinlet : public QskPopupSkinlet
QRectF subControlRect( const QskSkinnable*, QRectF subControlRect( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol ) const override; const QRectF&, QskAspect::Subcontrol ) const override;
QRectF subControlCell( const QskSkinnable*, int sampleCount( const QskSkinnable*, QskAspect::Subcontrol ) const override;
QRectF sampleRect( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol, int index ) const override; const QRectF&, QskAspect::Subcontrol, int index ) const override;
int subControlCellIndexAt( const QskSkinnable*, int sampleIndexAt( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol, const QPointF& ) const override; const QRectF&, QskAspect::Subcontrol, const QPointF& ) const override;
int subControlCellCount( const QskSkinnable*, QskAspect::Subcontrol ) const override; QskAspect::States sampleStates( const QskSkinnable*,
QskAspect::States subControlCellStates( const QskSkinnable*,
QskAspect::Subcontrol, int index ) const override; QskAspect::Subcontrol, int index ) const override;
QVariant valueAt( const QskSkinnable*, QVariant sampleAt( const QskSkinnable*,
QskAspect::Subcontrol, int index ) const override; QskAspect::Subcontrol, int index ) const override;
QSizeF sizeHint( const QskSkinnable*, QSizeF sizeHint( const QskSkinnable*,
@ -45,7 +45,7 @@ class QSK_EXPORT QskMenuSkinlet : public QskPopupSkinlet
QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const override; QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const override;
QSGNode* updateMenuNode( const QskSkinnable*, QSGNode* ) const; QSGNode* updateMenuNode( const QskSkinnable*, QSGNode* ) const;
QSGNode* updateSeriesSubNode( const QskSkinnable*, QSGNode* updateSampleNode( const QskSkinnable*,
QskAspect::Subcontrol, int index, QSGNode* ) const override; QskAspect::Subcontrol, int index, QSGNode* ) const override;
private: private:

View File

@ -564,20 +564,17 @@ QSGNode* QskSkinlet::updateGraphicNode(
return qskUpdateGraphicNode( skinnable, node, graphic, colorFilter, rect, mirrored ); return qskUpdateGraphicNode( skinnable, node, graphic, colorFilter, rect, mirrored );
} }
int QskSkinlet::subControlCellIndexAt( const QskSkinnable* skinnable, int QskSkinlet::sampleIndexAt( const QskSkinnable* skinnable,
const QRectF& rect, QskAspect::Subcontrol subControl, const QPointF& pos ) const const QRectF& rect, QskAspect::Subcontrol subControl, const QPointF& pos ) const
{ {
/* // slow default implementation to be overloaded when having many cells
slow default implementation to be overloaded when
having many cells
*/
const auto cellCount = subControlCellCount( skinnable, subControl ); const auto count = sampleCount( skinnable, subControl );
for ( int i = 0; i < cellCount; i++ ) for ( int i = 0; i < count; i++ )
{ {
const auto cellRect = subControlCell( skinnable, rect, subControl, i ); const auto r = sampleRect( skinnable, rect, subControl, i );
if ( cellRect.contains( pos ) ) if ( r.contains( pos ) )
return i; return i;
} }
@ -590,19 +587,19 @@ QSGNode* QskSkinlet::updateSeriesNode( const QskSkinnable* skinnable,
auto node = rootNode ? rootNode->firstChild() : nullptr; auto node = rootNode ? rootNode->firstChild() : nullptr;
QSGNode* lastNode = nullptr; QSGNode* lastNode = nullptr;
const auto count = subControlCellCount( skinnable, subControl ); const auto count = sampleCount( skinnable, subControl );
for( int i = 0; i < count; i++ ) for( int i = 0; i < count; i++ )
{ {
QSGNode* newNode = nullptr; QSGNode* newNode = nullptr;
{ {
const auto newStates = subControlCellStates( skinnable, subControl, i ); const auto newStates = sampleStates( skinnable, subControl, i );
QskSkinStateChanger stateChanger( skinnable ); QskSkinStateChanger stateChanger( skinnable );
stateChanger.setStates( newStates ); stateChanger.setStates( newStates );
newNode = updateSeriesSubNode( skinnable, subControl, i, node ); newNode = updateSampleNode( skinnable, subControl, i, node );
} }
if ( newNode ) if ( newNode )
@ -631,21 +628,21 @@ QSGNode* QskSkinlet::updateSeriesNode( const QskSkinnable* skinnable,
return rootNode; return rootNode;
} }
QSGNode* QskSkinlet::updateSeriesSubNode( const QskSkinnable*, QSGNode* QskSkinlet::updateSampleNode( const QskSkinnable*,
QskAspect::Subcontrol, int index, QSGNode* ) const QskAspect::Subcontrol, int index, QSGNode* ) const
{ {
Q_UNUSED( index ) Q_UNUSED( index )
return nullptr; return nullptr;
} }
QskAspect::States QskSkinlet::subControlCellStates( QskAspect::States QskSkinlet::sampleStates(
const QskSkinnable* skinnable, QskAspect::Subcontrol, int index ) const const QskSkinnable* skinnable, QskAspect::Subcontrol, int index ) const
{ {
Q_UNUSED( index ) Q_UNUSED( index )
return skinnable->skinStates(); return skinnable->skinStates();
} }
QVariant QskSkinlet::valueAt( const QskSkinnable*, QVariant QskSkinlet::sampleAt( const QskSkinnable*,
QskAspect::Subcontrol, int index ) const QskAspect::Subcontrol, int index ) const
{ {
Q_UNUSED( index ) Q_UNUSED( index )

View File

@ -42,18 +42,22 @@ class QSK_EXPORT QskSkinlet
virtual QRectF subControlRect( const QskSkinnable*, virtual QRectF subControlRect( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol ) const; const QRectF&, QskAspect::Subcontrol ) const;
virtual QRectF subControlCell( const QskSkinnable*, /*
When having more than one instance for the
same QskAspect::Subcontrol it is called a sample
*/
virtual QRectF sampleRect( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol, int index ) const; const QRectF&, QskAspect::Subcontrol, int index ) const;
virtual int subControlCellIndexAt( const QskSkinnable*, virtual int sampleIndexAt( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol, const QPointF& ) const; const QRectF&, QskAspect::Subcontrol, const QPointF& ) const;
virtual int subControlCellCount( const QskSkinnable*, QskAspect::Subcontrol ) const; virtual int sampleCount( const QskSkinnable*, QskAspect::Subcontrol ) const;
virtual QskAspect::States subControlCellStates( const QskSkinnable*, virtual QskAspect::States sampleStates( const QskSkinnable*,
QskAspect::Subcontrol, int index ) const; QskAspect::Subcontrol, int index ) const;
virtual QVariant valueAt( const QskSkinnable*, virtual QVariant sampleAt( const QskSkinnable*,
QskAspect::Subcontrol, int index ) const; QskAspect::Subcontrol, int index ) const;
const QVector< quint8 >& nodeRoles() const; const QVector< quint8 >& nodeRoles() const;
@ -61,6 +65,8 @@ class QSK_EXPORT QskSkinlet
void setOwnedBySkinnable( bool on ); void setOwnedBySkinnable( bool on );
bool isOwnedBySkinnable() const; bool isOwnedBySkinnable() const;
// Helper functions for creating nodes
static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*, static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,
const QRectF&, QskAspect::Subcontrol ); const QRectF&, QskAspect::Subcontrol );
@ -136,7 +142,7 @@ class QSK_EXPORT QskSkinlet
QSGNode* updateSeriesNode( const QskSkinnable*, QSGNode* updateSeriesNode( const QskSkinnable*,
QskAspect::Subcontrol, QSGNode* ) const; QskAspect::Subcontrol, QSGNode* ) const;
virtual QSGNode* updateSeriesSubNode( const QskSkinnable*, virtual QSGNode* updateSampleNode( const QskSkinnable*,
QskAspect::Subcontrol, int index, QSGNode* ) const; QskAspect::Subcontrol, int index, QSGNode* ) const;
void replaceChildNode( quint8 nodeRole, QSGNode* parentNode, void replaceChildNode( quint8 nodeRole, QSGNode* parentNode,
@ -168,17 +174,17 @@ inline QSizeF QskSkinlet::sizeHint(
return QSizeF(); return QSizeF();
} }
inline QRectF QskSkinlet::subControlCell( const QskSkinnable*, inline QRectF QskSkinlet::sampleRect( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol, int index ) const const QRectF&, QskAspect::Subcontrol, int index ) const
{ {
Q_UNUSED( index ) Q_UNUSED( index )
return QRectF(); return QRectF();
} }
inline int QskSkinlet::subControlCellCount( inline int QskSkinlet::sampleCount(
const QskSkinnable*, QskAspect::Subcontrol ) const const QskSkinnable*, QskAspect::Subcontrol ) const
{ {
return 1; return 0;
} }
#endif #endif