From 638ee038aa95b1631004102679cdb5807e828ccf Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 27 Jul 2023 17:03:34 +0200 Subject: [PATCH] trying to reorganize QskListViewSkinlet to be able to make use of updateSeriesNode and friends --- skins/squiek/QskSquiekSkin.cpp | 6 +- src/controls/QskListView.cpp | 33 +- src/controls/QskListView.h | 6 +- src/controls/QskListViewSkinlet.cpp | 461 +++++++++++++------------- src/controls/QskListViewSkinlet.h | 21 +- src/controls/QskScrollViewSkinlet.cpp | 20 +- src/controls/QskScrollViewSkinlet.h | 1 - 7 files changed, 263 insertions(+), 285 deletions(-) diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index f3afbcb6..65fa848d 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -1057,9 +1057,11 @@ void Editor::setupListView() // alternating row colors setColor( Q::Cell | A::Lower, Qt::white ); - setColor( Q::Cell | A::Upper, m_pal.contrasted ); + setColor( Q::Cell | Q::Selected | A::Lower, m_pal.highlighted ); + + setColor( Q::Cell | A::Upper, m_pal.contrasted ); + setColor( Q::Cell | Q::Selected | A::Upper, m_pal.highlighted ); - setColor( Q::Cell | Q::Selected, m_pal.highlighted ); setColor( Q::Text | Q::Selected, m_pal.highlightedText ); } diff --git a/src/controls/QskListView.cpp b/src/controls/QskListView.cpp index 0dbe237a..08e5cf44 100644 --- a/src/controls/QskListView.cpp +++ b/src/controls/QskListView.cpp @@ -16,11 +16,27 @@ QSK_SUBCONTROL( QskListView, Cell ) QSK_SUBCONTROL( QskListView, Text ) +QSK_SUBCONTROL( QskListView, Graphic ) QSK_STATE( QskListView, Selected, QskAspect::FirstUserState ) #define FOCUS_ON_CURRENT 1 +static inline int qskRowAt( const QskListView* listView, const QPointF& pos ) +{ + const auto rect = listView->viewContentsRect(); + if ( rect.contains( pos ) ) + { + const auto y = pos.y() - rect.top() + listView->scrollPos().y(); + + const int row = y / listView->rowHeight(); + if ( row >= 0 && row < listView->rowCount() ) + return row; + } + + return -1; +} + class QskListView::PrivateData { public: @@ -146,14 +162,6 @@ QskListView::SelectionMode QskListView::selectionMode() const return m_data->selectionMode; } -QskColorFilter QskListView::graphicFilterAt( int row, int col ) const -{ - Q_UNUSED( row ) - Q_UNUSED( col ) - - return QskColorFilter(); -} - QRectF QskListView::focusIndicatorRect() const { #if FOCUS_ON_CURRENT @@ -269,13 +277,10 @@ void QskListView::mousePressEvent( QMouseEvent* event ) { if ( m_data->selectionMode != NoSelection ) { - const QRectF vr = viewContentsRect(); - if ( vr.contains( event->pos() ) ) + const int row = qskRowAt( this, qskMousePosition( event ) ); + if ( row >= 0 ) { - const int row = ( event->pos().y() - vr.top() + scrollPos().y() ) / rowHeight(); - if ( row >= 0 && row < rowCount() ) - setSelectedRow( row ); - + setSelectedRow( row ); return; } } diff --git a/src/controls/QskListView.h b/src/controls/QskListView.h index a8de657c..13fe8055 100644 --- a/src/controls/QskListView.h +++ b/src/controls/QskListView.h @@ -29,7 +29,7 @@ class QSK_EXPORT QskListView : public QskScrollView using Inherited = QskScrollView; public: - QSK_SUBCONTROLS( Cell, Text ) + QSK_SUBCONTROLS( Cell, Text, Graphic ) QSK_STATES( Selected ) enum SelectionMode @@ -63,10 +63,6 @@ class QSK_EXPORT QskListView : public QskScrollView Q_INVOKABLE virtual QVariant valueAt( int row, int col ) const = 0; -#if 1 - virtual QskColorFilter graphicFilterAt( int row, int col ) const; -#endif - QRectF focusIndicatorRect() const override; public Q_SLOTS: diff --git a/src/controls/QskListViewSkinlet.cpp b/src/controls/QskListViewSkinlet.cpp index 236d66cb..91d8f226 100644 --- a/src/controls/QskListViewSkinlet.cpp +++ b/src/controls/QskListViewSkinlet.cpp @@ -11,78 +11,165 @@ #include "QskBoxHints.h" #include "QskSGNode.h" #include "QskSkinStateChanger.h" +#include "QskQuick.h" #include #include #include -class QskListViewNode final : public QSGTransformNode +namespace { - public: - inline QskListViewNode( int columnCount ) - : m_columnCount( columnCount ) + class ForegroundNode : public QSGNode { - m_backgroundNode.setFlag( QSGNode::OwnedByParent, false ); - appendChildNode( &m_backgroundNode ); + public: + void invalidate() + { + removeAllChildNodes(); + m_columnCount = m_oldRowMin = m_oldRowMax = -1; + } - m_foregroundNode.setFlag( QSGNode::OwnedByParent, false ); - appendChildNode( &m_foregroundNode ); + void rearrangeNodes( int rowMin, int rowMax, int columnCount ) + { + const bool doReorder = ( columnCount == m_columnCount ) + && ( rowMin <= m_oldRowMax ) && ( rowMax >= m_oldRowMin ); + + if ( doReorder ) + { + /* + We have nodes that will be at a different position in the + list of child nodes - however their content might be unchanged. + + This is a common situation, when resizing or scrolling the list. + + To avoid that the text/graphic nodes have to be updated we + try to rearrange the nodes, so that they are in increasing + row order for further processing. + + To avoid delete/new calls we append the leading and prepend + the trailing nodes, so that they might be used later. + */ + + if ( rowMin >= m_oldRowMin ) + { + for ( int row = m_oldRowMin; row < rowMin; row++ ) + { + for ( int col = 0; col < columnCount; col++ ) + { + auto childNode = firstChild(); + removeChildNode( childNode ); + appendChildNode( childNode ); + } + } + } + else + { + for ( int row = rowMin; row < m_oldRowMin; row++ ) + { + for ( int col = 0; col < columnCount; col++ ) + { + auto childNode = lastChild(); + removeChildNode( childNode ); + prependChildNode( childNode ); + } + } + } + } + + m_oldRowMin = rowMin; + m_oldRowMax = rowMax; + m_columnCount = columnCount; + } + + private: + /* + When scrolling the majority of the child nodes are simply translated + while only few rows appear/disappear. To implement this in an efficient + way we store how the nodes were related to the rows in the previous update, + */ + + int m_oldRowMin = -1; + int m_oldRowMax = -1; + int m_columnCount = -1; + }; + + class ListViewNode final : public QSGTransformNode + { + public: + inline ListViewNode() + { + m_backgroundNode.setFlag( QSGNode::OwnedByParent, false ); + appendChildNode( &m_backgroundNode ); + + m_foregroundNode.setFlag( QSGNode::OwnedByParent, false ); + appendChildNode( &m_foregroundNode ); + } + + void initialize( const QskListView* listView ) + { + const auto scrollPos = listView->scrollPos(); + setMatrix( QTransform::fromTranslate( -scrollPos.x(), -scrollPos.y() ) ); + + m_clipRect = listView->viewContentsRect(); + m_rowHeight = listView->rowHeight(); + + m_rowMin = qFloor( scrollPos.y() / m_rowHeight ); + + const auto rowMax = ( scrollPos.y() + m_clipRect.height() ) / m_rowHeight; + m_rowMax = qFloor( rowMax - 10e-6 ); + + if ( m_rowMax >= listView->rowCount() ) + m_rowMax = listView->rowCount() - 1; + } + + QRectF clipRect() const { return m_clipRect; } + + int rowMin() const { return m_rowMin; } + int rowMax() const { return m_rowMax; } + int rowCount() const { return m_rowMax - m_rowMin + 1; } + + int rowHeight() const { return m_rowHeight; } + + QSGNode* backgroundNode() { return &m_backgroundNode; } + ForegroundNode* foregroundNode() { return &m_foregroundNode; } + + private: + // caching some calculations to speed things up + + QRectF m_clipRect; + qreal m_rowHeight; + + int m_rowMin, m_rowMax; + + QSGNode m_backgroundNode; + ForegroundNode m_foregroundNode; + }; +} + +static inline ListViewNode* qskListViewNode( const QskListView* listView ) +{ + if ( auto node = const_cast< QSGNode* >( qskPaintNode( listView ) ) ) + { + using namespace QskSGNode; + + node = findChildNode( node, QskScrollViewSkinlet::ContentsRootRole ); + if ( node ) + { + node = node->firstChild(); + if ( node ) + { + Q_ASSERT( node->type() == QSGNode::TransformNodeType ); + return static_cast< ListViewNode* >( node ); + } + } } - QSGNode* backgroundNode() - { - return &m_backgroundNode; - } + return nullptr; +} - QSGNode* foregroundNode() - { - return &m_foregroundNode; - } - - inline void resetRows( int rowMin, int rowMax ) - { - m_rowMin = rowMin; - m_rowMax = rowMax; - } - - inline int rowMin() const - { - return m_rowMin; - } - - inline int rowMax() const - { - return m_rowMax; - } - - inline bool intersects( int rowMin, int rowMax ) const - { - return ( rowMin <= m_rowMax ) && ( rowMax >= m_rowMin ); - } - - inline int nodeCount() const - { - return ( m_rowMin >= 0 ) ? ( m_rowMax - m_rowMin + 1 ) * m_columnCount : 0; - } - - inline int columnCount() const - { - return m_columnCount; - } - - inline void invalidate() - { - m_rowMin = m_rowMax = -1; - } - - private: - int m_columnCount; - int m_rowMin = -1; - int m_rowMax = -1; - - QSGNode m_backgroundNode; - QSGNode m_foregroundNode; -}; +static inline ListViewNode* qskListViewNode( const QskSkinnable* skinnable ) +{ + return qskListViewNode( static_cast< const QskListView* >( skinnable ) ); +} QskListViewSkinlet::QskListViewSkinlet( QskSkin* skin ) : Inherited( skin ) @@ -96,57 +183,36 @@ QSGNode* QskListViewSkinlet::updateContentsNode( { const auto listView = static_cast< const QskListView* >( scrollView ); - auto listViewNode = static_cast< QskListViewNode* >( node ); - if ( listViewNode == nullptr ) - listViewNode = new QskListViewNode( listView->columnCount() ); + auto listViewNode = QskSGNode::ensureNode< ListViewNode >( node ); + listViewNode->initialize( listView ); - QTransform transform; - transform.translate( -listView->scrollPos().x(), -listView->scrollPos().y() ); - listViewNode->setMatrix( transform ); - - updateBackgroundNodes( listView, listViewNode ); - updateForegroundNodes( listView, listViewNode ); + updateBackgroundNodes( listView, listViewNode->backgroundNode() ); + updateForegroundNodes( listView, listViewNode->foregroundNode() ); return listViewNode; } void QskListViewSkinlet::updateBackgroundNodes( - const QskListView* listView, QskListViewNode* listViewNode ) const + const QskListView* listView, QSGNode* backgroundNode ) const { using Q = QskListView; using A = QskAspect; - auto backgroundNode = listViewNode->backgroundNode(); - - const auto cellHeight = listView->rowHeight(); - const auto viewRect = listView->viewContentsRect(); - - const auto scrolledPos = listView->scrollPos(); - const int rowMin = qFloor( scrolledPos.y() / cellHeight ); - - int rowMax = qCeil( ( scrolledPos.y() + viewRect.height() ) / cellHeight ); - if ( rowMax >= listView->rowCount() ) - rowMax = listView->rowCount() - 1; - - const auto x0 = viewRect.left() + scrolledPos.x(); - const auto y0 = viewRect.top(); + auto listViewNode = static_cast< const ListViewNode* >( backgroundNode->parent() ); auto rowNode = backgroundNode->firstChild(); - const auto boxHints1 = listView->boxHints( Q::Cell | A::Lower ); - const auto boxHints2 = listView->boxHints( Q::Cell | A::Upper ); - - for ( int row = rowMin; row <= rowMax; row++ ) + for ( int row = listViewNode->rowMin(); row <= listViewNode->rowMax(); row++ ) { - /* - We do not use sampleRect to avoid doing the calculation - of viewRect for each row. - */ - const QRectF rect( x0, y0 + row * cellHeight, viewRect.width(), cellHeight ); + QskSkinStateChanger stateChanger( listView ); + stateChanger.setStates( sampleStates( listView, Q::Cell, row ) ); - auto newNode = updateBoxNode( listView, rowNode, rect, - ( row % 2 ) ? boxHints2 : boxHints1 ); + const auto rect = sampleRect( listView, listView->contentsRect(), Q::Cell, row ); + const QskAspect aspect = Q::Cell | ( ( row % 2 ) ? A::Upper : A::Lower ); + const auto boxHints = listView->boxHints( aspect ); + + auto newNode = updateBoxNode( listView, rowNode, rect, boxHints ); if ( newNode ) { if ( newNode->parent() != backgroundNode ) @@ -156,45 +222,28 @@ void QskListViewSkinlet::updateBackgroundNodes( } } - const int rowSelected = listView->selectedRow(); - if ( rowSelected >= rowMin && rowSelected <= rowMax ) - { - QskSkinStateChanger stateChanger( listView ); - stateChanger.setStates( listView->skinStates() | QskListView::Selected ); - - const QRectF rect( x0, y0 + rowSelected * cellHeight, - viewRect.width(), cellHeight ); - - rowNode = updateBoxNode( listView, rowNode, rect, Q::Cell ); - if ( rowNode && rowNode->parent() != backgroundNode ) - backgroundNode->appendChildNode( rowNode ); - } - - QskSGNode::removeAllChildNodesAfter( backgroundNode, rowNode ); + QskSGNode::removeAllChildNodesFrom( backgroundNode, rowNode ); } void QskListViewSkinlet::updateForegroundNodes( - const QskListView* listView, QskListViewNode* listViewNode ) const + const QskListView* listView, QSGNode* parentNode ) const { - auto parentNode = listViewNode->foregroundNode(); + auto foregroundNode = static_cast< ForegroundNode* >( parentNode ); if ( listView->rowCount() <= 0 || listView->columnCount() <= 0 ) { - parentNode->removeAllChildNodes(); - listViewNode->invalidate(); + foregroundNode->invalidate(); return; } - const auto margins = listView->paddingHint( QskListView::Cell ); + auto listViewNode = static_cast< const ListViewNode* >( parentNode->parent() ); - const auto cr = listView->viewContentsRect(); - const auto scrolledPos = listView->scrollPos(); + const auto clipRect = listViewNode->clipRect(); - const int rowMin = qFloor( scrolledPos.y() / listView->rowHeight() ); + const int rowMin = listViewNode->rowMin(); + const int rowMax = listViewNode->rowMax(); - int rowMax = rowMin + qCeil( cr.height() / listView->rowHeight() ); - if ( rowMax >= listView->rowCount() ) - rowMax = listView->rowCount() - 1; + foregroundNode->rearrangeNodes( rowMin, rowMax, listView->columnCount() ); #if 1 // should be optimized for visible columns only @@ -202,67 +251,28 @@ void QskListViewSkinlet::updateForegroundNodes( const int colMax = listView->columnCount() - 1; #endif - bool forwards = true; + const auto margins = listView->paddingHint( QskListView::Cell ); - if ( listViewNode->intersects( rowMin, rowMax ) ) - { - /* - We try to avoid reallcations when scrolling, by reusing - the nodes of the cells leaving the viewport for those becoming visible. - */ - - forwards = ( rowMin >= listViewNode->rowMin() ); - - if ( forwards ) - { - // usually scrolling down - for ( int row = listViewNode->rowMin(); row < rowMin; row++ ) - { - for ( int col = 0; col < listView->columnCount(); col++ ) - { - QSGNode* childNode = parentNode->firstChild(); - parentNode->removeChildNode( childNode ); - parentNode->appendChildNode( childNode ); - } - } - } - else - { - // usually scrolling up - for ( int row = rowMax; row < listViewNode->rowMax(); row++ ) - { - for ( int col = 0; col < listView->columnCount(); col++ ) - { - QSGNode* childNode = parentNode->lastChild(); - parentNode->removeChildNode( childNode ); - parentNode->prependChildNode( childNode ); - } - } - } - } - - updateVisibleForegroundNodes( listView, listViewNode, - rowMin, rowMax, colMin, colMax, margins, forwards ); + updateVisibleForegroundNodes( + listView, foregroundNode, rowMin, rowMax, margins ); // finally putting the nodes into their position - auto node = parentNode->firstChild(); + auto node = foregroundNode->firstChild(); const auto rowHeight = listView->rowHeight(); - auto y = cr.top() + rowMin * rowHeight; + auto y = clipRect.top() + rowMin * rowHeight; for ( int row = rowMin; row <= rowMax; row++ ) { - qreal x = cr.left(); + qreal x = clipRect.left(); for ( int col = colMin; col <= colMax; col++ ) { Q_ASSERT( node->type() == QSGNode::TransformNodeType ); auto transformNode = static_cast< QSGTransformNode* >( node ); - QTransform transform; - transform.translate( x + margins.left(), y + margins.top() ); - - transformNode->setMatrix( transform ); + transformNode->setMatrix( + QTransform::fromTranslate( x + margins.left(), y + margins.top() ) ); node = node->nextSibling(); x += listView->columnWidth( col ); @@ -270,72 +280,36 @@ void QskListViewSkinlet::updateForegroundNodes( y += rowHeight; } - - listViewNode->resetRows( rowMin, rowMax ); } void QskListViewSkinlet::updateVisibleForegroundNodes( - const QskListView* listView, QskListViewNode* listViewNode, - int rowMin, int rowMax, int colMin, int colMax, const QMarginsF& margins, - bool forward ) const + const QskListView* listView, QSGNode* parentNode, + int rowMin, int rowMax, const QMarginsF& margins ) const { - auto parentNode = listViewNode->foregroundNode(); + auto node = parentNode->firstChild(); - const int rowCount = rowMax - rowMin + 1; - const int colCount = colMax - colMin + 1; - const int obsoleteNodesCount = listViewNode->nodeCount() - rowCount * colCount; - - if ( forward ) + for ( int row = rowMin; row <= rowMax; row++ ) { - for ( int i = 0; i < obsoleteNodesCount; i++ ) - delete parentNode->lastChild(); + const auto h = listView->rowHeight() - ( margins.top() + margins.bottom() ); - auto node = parentNode->firstChild(); - - for ( int row = rowMin; row <= rowMax; row++ ) + for ( int col = 0; col < listView->columnCount(); col++ ) { - const auto h = listView->rowHeight() - ( margins.top() + margins.bottom() ); + const auto w = listView->columnWidth( col ) - ( margins.left() + margins.right() ); - for ( int col = 0; col < listView->columnCount(); col++ ) - { - const auto w = listView->columnWidth( col ) - ( margins.left() + margins.right() ); + node = updateForegroundNode( listView, + parentNode, static_cast< QSGTransformNode* >( node ), + row, col, QSizeF( w, h ) ); - node = updateForegroundNode( listView, - parentNode, static_cast< QSGTransformNode* >( node ), - row, col, QSizeF( w, h ), forward ); - - node = node->nextSibling(); - } + node = node->nextSibling(); } } - else - { - for ( int i = 0; i < obsoleteNodesCount; i++ ) - delete parentNode->firstChild(); - auto* node = parentNode->lastChild(); - - for ( int row = rowMax; row >= rowMin; row-- ) - { - const qreal h = listView->rowHeight() - ( margins.top() + margins.bottom() ); - - for ( int col = listView->columnCount() - 1; col >= 0; col-- ) - { - const auto w = listView->columnWidth( col ) - ( margins.left() + margins.right() ); - - node = updateForegroundNode( listView, - parentNode, static_cast< QSGTransformNode* >( node ), - row, col, QSizeF( w, h ), forward ); - - node = node->previousSibling(); - } - } - } + QskSGNode::removeAllChildNodesFrom( parentNode, node ); } QSGTransformNode* QskListViewSkinlet::updateForegroundNode( const QskListView* listView, QSGNode* parentNode, QSGTransformNode* cellNode, - int row, int col, const QSizeF& size, bool forward ) const + int row, int col, const QSizeF& size ) const { const QRectF cellRect( 0.0, 0.0, size.width(), size.height() ); @@ -407,10 +381,7 @@ QSGTransformNode* QskListViewSkinlet::updateForegroundNode( } else { - if ( forward ) - parentNode->appendChildNode( newCellNode ); - else - parentNode->prependChildNode( newCellNode ); + parentNode->appendChildNode( newCellNode ); } } @@ -420,14 +391,11 @@ QSGTransformNode* QskListViewSkinlet::updateForegroundNode( QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView, QSGNode* contentNode, const QRectF& rect, int row, int col ) const { + using Q = QskListView; using namespace QskSGNode; - auto rowStates = listView->skinStates(); - if ( row == listView->selectedRow() ) - rowStates |= QskListView::Selected; - QskSkinStateChanger stateChanger( listView ); - stateChanger.setStates( rowStates ); + stateChanger.setStates( sampleStates( listView, Q::Cell, row ) ); QSGNode* newNode = nullptr; @@ -439,7 +407,7 @@ QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView, */ #endif const auto alignment = listView->alignmentHint( - QskListView::Cell, Qt::AlignVCenter | Qt::AlignLeft ); + Q::Cell, Qt::AlignVCenter | Qt::AlignLeft ); const auto value = listView->valueAt( row, col ); @@ -448,7 +416,7 @@ QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView, if ( nodeRole( contentNode ) == GraphicRole ) newNode = contentNode; - const auto colorFilter = listView->graphicFilterAt( row, col ); + const auto colorFilter = listView->effectiveGraphicFilter( Q::Graphic ); newNode = updateGraphicNode( listView, newNode, value.value< QskGraphic >(), colorFilter, rect, alignment ); @@ -462,7 +430,7 @@ QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView, newNode = contentNode; newNode = updateTextNode( listView, newNode, rect, alignment, - value.toString(), QskListView::Text ); + value.toString(), Q::Text ); if ( newNode ) setNodeRole( newNode, TextRole ); @@ -494,22 +462,43 @@ QSizeF QskListViewSkinlet::sizeHint( const QskSkinnable* skinnable, return QSizeF( w, -1.0 ); } +QskAspect::States QskListViewSkinlet::sampleStates( const QskSkinnable* skinnable, + QskAspect::Subcontrol subControl, int index ) const +{ + using Q = QskListView; + + if ( subControl == Q::Cell || subControl == Q::Text || subControl == Q::Graphic ) + { + const auto listView = static_cast< const QskListView* >( skinnable ); + + auto states = listView->skinStates(); + if ( index == listView->selectedRow() ) + states |= Q::Selected; + + return states; + } + + return Inherited::sampleStates( skinnable, subControl, index ); +} + QRectF QskListViewSkinlet::sampleRect( const QskSkinnable* skinnable, const QRectF& contentsRect, QskAspect::Subcontrol subControl, int index ) const { using Q = QskListView; + const auto listView = static_cast< const QskListView* >( skinnable ); if ( subControl == Q::Cell ) { - const auto cellHeight = listView->rowHeight(); - const auto viewRect = listView->viewContentsRect(); - const auto scrolledPos = listView->scrollPos(); + auto node = qskListViewNode( listView ); + const auto clipRect = node ? node->clipRect() : listView->viewContentsRect(); - const double x0 = viewRect.left() + scrolledPos.x(); - const double y0 = viewRect.top(); + const auto w = clipRect.width(); + const auto h = listView->rowHeight(); + const auto x = clipRect.left() + listView->scrollPos().x(); + const auto y = clipRect.top() + index * h; - return QRectF( x0, y0 + index * cellHeight, viewRect.width(), cellHeight ); + return QRectF( x, y, w, h ); } return Inherited::sampleRect( skinnable, contentsRect, subControl, index ); diff --git a/src/controls/QskListViewSkinlet.h b/src/controls/QskListViewSkinlet.h index 4f174962..e26f4cb1 100644 --- a/src/controls/QskListViewSkinlet.h +++ b/src/controls/QskListViewSkinlet.h @@ -9,7 +9,6 @@ #include "QskScrollViewSkinlet.h" class QskListView; -class QskListViewNode; class QMarginsF; class QSizeF; @@ -40,25 +39,27 @@ class QSK_EXPORT QskListViewSkinlet : public QskScrollViewSkinlet QRectF sampleRect( const QskSkinnable*, const QRectF&, QskAspect::Subcontrol, int index ) const override; + QskAspect::States sampleStates( const QskSkinnable*, + QskAspect::Subcontrol, int index ) const override; + protected: QSGNode* updateContentsNode( const QskScrollView*, QSGNode* ) const override; - virtual QSGNode* updateCellNode( const QskListView*, - QSGNode*, const QRectF&, int row, int col ) const; - private: - void updateForegroundNodes( const QskListView*, QskListViewNode* ) const; - void updateBackgroundNodes( const QskListView*, QskListViewNode* ) const; + void updateForegroundNodes( const QskListView*, QSGNode* ) const; + void updateBackgroundNodes( const QskListView*, QSGNode* ) const; void updateVisibleForegroundNodes( - const QskListView*, QskListViewNode*, - int rowMin, int rowMax, int colMin, int colMax, - const QMarginsF& margin, bool forward ) const; + const QskListView*, QSGNode*, + int rowMin, int rowMax, const QMarginsF& margin ) const; QSGTransformNode* updateForegroundNode( const QskListView*, QSGNode* parentNode, QSGTransformNode* cellNode, - int row, int col, const QSizeF&, bool forward ) const; + int row, int col, const QSizeF& ) const; + + QSGNode* updateCellNode( const QskListView*, + QSGNode*, const QRectF&, int row, int col ) const; }; #endif diff --git a/src/controls/QskScrollViewSkinlet.cpp b/src/controls/QskScrollViewSkinlet.cpp index 3bc10a11..3ab7848e 100644 --- a/src/controls/QskScrollViewSkinlet.cpp +++ b/src/controls/QskScrollViewSkinlet.cpp @@ -17,7 +17,9 @@ static void qskAlignedHandle( qreal start, qreal end, qreal scrollBarLength, qreal minHandleLength, qreal& handleStart, qreal& handleEnd ) { - minHandleLength = qBound( 4.0, minHandleLength, scrollBarLength ); + // no qBound: scrollBarLength might be < 4.0 + minHandleLength = qMax( 4.0, minHandleLength ); + minHandleLength = qMin( minHandleLength, scrollBarLength ); handleStart = start * scrollBarLength; handleEnd = end * scrollBarLength; @@ -178,22 +180,6 @@ QSGNode* QskScrollViewSkinlet::updateContentsNode( return nullptr; } -QSGNode* QskScrollViewSkinlet::contentsNode( const QskScrollView* scrollView ) -{ - if ( auto node = const_cast< QSGNode* >( qskPaintNode( scrollView ) ) ) - { - node = QskSGNode::findChildNode( node, ContentsRootRole ); - if ( node ) - { - node = node->firstChild(); - if ( node ) - return node->firstChild(); - } - } - - return nullptr; -} - QRectF QskScrollViewSkinlet::viewportRect( const QskScrollView* scrollView, const QRectF& contentsRect ) const { diff --git a/src/controls/QskScrollViewSkinlet.h b/src/controls/QskScrollViewSkinlet.h index 16c6c81f..0bc9d190 100644 --- a/src/controls/QskScrollViewSkinlet.h +++ b/src/controls/QskScrollViewSkinlet.h @@ -43,7 +43,6 @@ class QSK_EXPORT QskScrollViewSkinlet : public QskSkinlet quint8 nodeRole, QSGNode* ) const override; virtual QSGNode* updateContentsNode( const QskScrollView*, QSGNode* ) const; - QSGNode* contentsNode( const QskScrollView* ); private: QSGNode* updateContentsRootNode( const QskScrollView*, QSGNode* ) const;