trying to reduce the number of updates
This commit is contained in:
parent
0cdff58c93
commit
3d77cfbb7a
|
@ -12,7 +12,44 @@ QSK_QT_PRIVATE_BEGIN
|
||||||
#include <private/qquickitem_p.h>
|
#include <private/qquickitem_p.h>
|
||||||
QSK_QT_PRIVATE_END
|
QSK_QT_PRIVATE_END
|
||||||
|
|
||||||
QQuickAnchors* qskGetOrCreateAnchors( QQuickItem* item )
|
namespace
|
||||||
|
{
|
||||||
|
struct AnchorLineOperators
|
||||||
|
{
|
||||||
|
QQuickAnchorLine ( QQuickAnchors::*line ) () const;
|
||||||
|
void ( QQuickAnchors::*setLine )( const QQuickAnchorLine& );
|
||||||
|
void ( QQuickAnchors::*resetLine )();
|
||||||
|
};
|
||||||
|
|
||||||
|
class UpdateBlocker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UpdateBlocker( QQuickAnchors* anchors )
|
||||||
|
: m_anchors( anchors )
|
||||||
|
{
|
||||||
|
auto d = QQuickAnchorsPrivate::get( anchors );
|
||||||
|
|
||||||
|
m_wasComplete = d->componentComplete;
|
||||||
|
d->componentComplete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
~UpdateBlocker()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() const
|
||||||
|
{
|
||||||
|
auto d = QQuickAnchorsPrivate::get( m_anchors );
|
||||||
|
d->componentComplete = m_wasComplete;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
QQuickAnchors* m_anchors;
|
||||||
|
bool m_wasComplete;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QQuickAnchors* qskGetOrCreateAnchors( QQuickItem* item )
|
||||||
{
|
{
|
||||||
if ( item == nullptr )
|
if ( item == nullptr )
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -20,7 +57,7 @@ QQuickAnchors* qskGetOrCreateAnchors( QQuickItem* item )
|
||||||
return QQuickItemPrivate::get( item )->anchors();
|
return QQuickItemPrivate::get( item )->anchors();
|
||||||
}
|
}
|
||||||
|
|
||||||
QQuickAnchors* qskGetAnchors( QQuickItem* item )
|
static inline QQuickAnchors* qskGetAnchors( QQuickItem* item )
|
||||||
{
|
{
|
||||||
if ( item == nullptr )
|
if ( item == nullptr )
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -28,15 +65,13 @@ QQuickAnchors* qskGetAnchors( QQuickItem* item )
|
||||||
return QQuickItemPrivate::get( item )->_anchors;
|
return QQuickItemPrivate::get( item )->_anchors;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QQuickAnchors* qskGetAnchors( const QQuickItem* item )
|
static inline const QQuickAnchors* qskGetAnchors( const QQuickItem* item )
|
||||||
{
|
{
|
||||||
return qskGetAnchors( const_cast< QQuickItem* >( item ) );
|
return qskGetAnchors( const_cast< QQuickItem* >( item ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
static inline QQuickAnchors::Anchor qskToQuickAnchor( Qt::AnchorPoint edge )
|
||||||
{
|
{
|
||||||
inline QQuickAnchors::Anchor toQuickAnchor( Qt::AnchorPoint edge )
|
|
||||||
{
|
|
||||||
using A = QQuickAnchors;
|
using A = QQuickAnchors;
|
||||||
|
|
||||||
switch( edge )
|
switch( edge )
|
||||||
|
@ -49,10 +84,10 @@ namespace
|
||||||
case Qt::AnchorBottom: return A::BottomAnchor;
|
case Qt::AnchorBottom: return A::BottomAnchor;
|
||||||
default: return A::InvalidAnchor;
|
default: return A::InvalidAnchor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Qt::AnchorPoint toAnchorPoint( QQuickAnchors::Anchor anchor )
|
static inline Qt::AnchorPoint qskToAnchorPoint( QQuickAnchors::Anchor anchor )
|
||||||
{
|
{
|
||||||
using A = QQuickAnchors;
|
using A = QQuickAnchors;
|
||||||
|
|
||||||
switch( anchor )
|
switch( anchor )
|
||||||
|
@ -66,26 +101,19 @@ namespace
|
||||||
case A::BaselineAnchor: return Qt::AnchorTop; // not supported
|
case A::BaselineAnchor: return Qt::AnchorTop; // not supported
|
||||||
default: return Qt::AnchorLeft;
|
default: return Qt::AnchorLeft;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isCenterAnchorPoint( Qt::AnchorPoint edge )
|
static inline bool qskIsCenterAnchorPoint( Qt::AnchorPoint edge )
|
||||||
{
|
{
|
||||||
return ( edge == Qt::AnchorHorizontalCenter )
|
return ( edge == Qt::AnchorHorizontalCenter )
|
||||||
|| ( edge == Qt::AnchorVerticalCenter );
|
|| ( edge == Qt::AnchorVerticalCenter );
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AnchorOperators
|
static inline const AnchorLineOperators& qskAnchorLineOperators( Qt::AnchorPoint edge )
|
||||||
{
|
{
|
||||||
QQuickAnchorLine ( QQuickAnchors::*line ) () const;
|
|
||||||
void ( QQuickAnchors::*setLine )( const QQuickAnchorLine& );
|
|
||||||
void ( QQuickAnchors::*resetLine )();
|
|
||||||
};
|
|
||||||
|
|
||||||
const AnchorOperators& operators( Qt::AnchorPoint edge )
|
|
||||||
{
|
|
||||||
using A = QQuickAnchors;
|
using A = QQuickAnchors;
|
||||||
|
|
||||||
static constexpr AnchorOperators table[] =
|
static constexpr AnchorLineOperators table[] =
|
||||||
{
|
{
|
||||||
// in order of Qt::AnchorPoint
|
// in order of Qt::AnchorPoint
|
||||||
|
|
||||||
|
@ -98,7 +126,6 @@ namespace
|
||||||
};
|
};
|
||||||
|
|
||||||
return table[edge];
|
return table[edge];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QskItemAnchors::QskItemAnchors( QQuickItem* attachedItem )
|
QskItemAnchors::QskItemAnchors( QQuickItem* attachedItem )
|
||||||
|
@ -142,12 +169,36 @@ void QskItemAnchors::setMargins( const QMarginsF& margins )
|
||||||
if ( anchors == nullptr )
|
if ( anchors == nullptr )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( margins != this->margins() )
|
const auto oldMargins = this->margins();
|
||||||
|
|
||||||
|
Qt::Orientations changes;
|
||||||
|
|
||||||
|
if ( margins.left() != oldMargins.left() )
|
||||||
|
changes |= Qt::Horizontal;
|
||||||
|
|
||||||
|
if ( margins.right() != oldMargins.right() )
|
||||||
|
changes |= Qt::Horizontal;
|
||||||
|
|
||||||
|
if ( margins.top() != oldMargins.top() )
|
||||||
|
changes |= Qt::Vertical;
|
||||||
|
|
||||||
|
if ( margins.bottom() != oldMargins.bottom() )
|
||||||
|
changes |= Qt::Vertical;
|
||||||
|
|
||||||
|
if ( changes )
|
||||||
{
|
{
|
||||||
anchors->setLeftMargin( margins.left() );
|
const auto left = margins.left();
|
||||||
|
|
||||||
|
UpdateBlocker blocker( anchors );
|
||||||
|
|
||||||
|
anchors->setLeftMargin( left + 1.0 );
|
||||||
anchors->setRightMargin( margins.right() );
|
anchors->setRightMargin( margins.right() );
|
||||||
anchors->setTopMargin( margins.top() );
|
anchors->setTopMargin( margins.top() );
|
||||||
anchors->setBottomMargin( margins.bottom() );
|
anchors->setBottomMargin( margins.bottom() );
|
||||||
|
|
||||||
|
blocker.reset();
|
||||||
|
|
||||||
|
anchors->setLeftMargin( left ); // trigger final update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,17 +244,17 @@ QQuickItem* QskItemAnchors::settledItem( Qt::AnchorPoint edge ) const
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if ( auto fill = anchors->fill() )
|
if ( auto fill = anchors->fill() )
|
||||||
return !isCenterAnchorPoint( edge ) ? fill : nullptr;
|
return !qskIsCenterAnchorPoint( edge ) ? fill : nullptr;
|
||||||
|
|
||||||
if ( auto centerIn = anchors->centerIn() )
|
if ( auto centerIn = anchors->centerIn() )
|
||||||
return isCenterAnchorPoint( edge ) ? centerIn : nullptr;
|
return qskIsCenterAnchorPoint( edge ) ? centerIn : nullptr;
|
||||||
|
|
||||||
const auto& ops = operators( edge );
|
const auto& ops = qskAnchorLineOperators( edge );
|
||||||
return ( ( anchors->*ops.line ) () ).item;
|
return ( ( anchors->*ops.line ) () ).item;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskItemAnchors::addAnchors( Qt::Corner corner,
|
void QskItemAnchors::addAnchors( Qt::Corner corner,
|
||||||
QQuickItem* baseItem, Qt::Corner baseCorner )
|
QQuickItem* settledItem, Qt::Corner settledItemCorner )
|
||||||
{
|
{
|
||||||
auto anchorPoint =
|
auto anchorPoint =
|
||||||
[]( Qt::Corner corner, Qt::Orientation orientation )
|
[]( Qt::Corner corner, Qt::Orientation orientation )
|
||||||
|
@ -215,22 +266,22 @@ void QskItemAnchors::addAnchors( Qt::Corner corner,
|
||||||
};
|
};
|
||||||
|
|
||||||
addAnchor( anchorPoint( corner, Qt::Horizontal ),
|
addAnchor( anchorPoint( corner, Qt::Horizontal ),
|
||||||
baseItem, anchorPoint( baseCorner, Qt::Horizontal ) );
|
settledItem, anchorPoint( settledItemCorner, Qt::Horizontal ) );
|
||||||
|
|
||||||
addAnchor( anchorPoint( corner, Qt::Vertical ),
|
addAnchor( anchorPoint( corner, Qt::Vertical ),
|
||||||
baseItem, anchorPoint( baseCorner, Qt::Vertical ) );
|
settledItem, anchorPoint( settledItemCorner, Qt::Vertical ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskItemAnchors::addAnchor( Qt::AnchorPoint edge, QQuickItem* baseItem,
|
void QskItemAnchors::addAnchor( Qt::AnchorPoint edge, QQuickItem* settledItem,
|
||||||
Qt::AnchorPoint baseEdge )
|
Qt::AnchorPoint settledItemEdge )
|
||||||
{
|
{
|
||||||
if ( baseItem == nullptr )
|
if ( settledItem == nullptr )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( const auto anchors = qskGetOrCreateAnchors( m_attachedItem ) )
|
if ( const auto anchors = qskGetOrCreateAnchors( m_attachedItem ) )
|
||||||
{
|
{
|
||||||
const auto& ops = operators( edge );
|
const auto& ops = qskAnchorLineOperators( edge );
|
||||||
( anchors->*ops.setLine )( { baseItem, toQuickAnchor( baseEdge ) } );
|
( anchors->*ops.setLine )( { settledItem, qskToQuickAnchor( settledItemEdge ) } );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +293,7 @@ void QskItemAnchors::removeAnchor( Qt::AnchorPoint edge )
|
||||||
|
|
||||||
if ( auto fill = anchors->fill() )
|
if ( auto fill = anchors->fill() )
|
||||||
{
|
{
|
||||||
if ( !isCenterAnchorPoint( edge ) )
|
if ( !qskIsCenterAnchorPoint( edge ) )
|
||||||
{
|
{
|
||||||
anchors->resetFill();
|
anchors->resetFill();
|
||||||
|
|
||||||
|
@ -260,7 +311,7 @@ void QskItemAnchors::removeAnchor( Qt::AnchorPoint edge )
|
||||||
|
|
||||||
if ( auto centerIn = anchors->centerIn() )
|
if ( auto centerIn = anchors->centerIn() )
|
||||||
{
|
{
|
||||||
if ( isCenterAnchorPoint( edge ) )
|
if ( qskIsCenterAnchorPoint( edge ) )
|
||||||
{
|
{
|
||||||
anchors->resetCenterIn();
|
anchors->resetCenterIn();
|
||||||
|
|
||||||
|
@ -274,77 +325,98 @@ void QskItemAnchors::removeAnchor( Qt::AnchorPoint edge )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& ops = operators( edge );
|
const auto& ops = qskAnchorLineOperators( edge );
|
||||||
( anchors->*ops.resetLine ) ();
|
( anchors->*ops.resetLine ) ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskItemAnchors::clearAnchors()
|
void QskItemAnchors::clearAnchors()
|
||||||
{
|
{
|
||||||
if ( const auto anchors = qskGetAnchors( m_attachedItem ) )
|
const auto anchors = qskGetAnchors( m_attachedItem );
|
||||||
{
|
if ( anchors == nullptr )
|
||||||
|
return;
|
||||||
|
|
||||||
|
const UpdateBlocker blocker( anchors );
|
||||||
|
|
||||||
anchors->resetFill();
|
anchors->resetFill();
|
||||||
anchors->resetCenterIn();
|
anchors->resetCenterIn();
|
||||||
|
|
||||||
for ( int i = 0; i < 6; i++ )
|
for ( int i = 0; i < 6; i++ )
|
||||||
{
|
{
|
||||||
const auto& ops = operators( static_cast< Qt::AnchorPoint >( i ) );
|
const auto& ops = qskAnchorLineOperators( static_cast< Qt::AnchorPoint >( i ) );
|
||||||
( anchors->*ops.resetLine ) ();
|
( anchors->*ops.resetLine ) ();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskItemAnchors::setBorderAnchors( QQuickItem* baseItem, Qt::Orientations orientations )
|
void QskItemAnchors::setBorderAnchors(
|
||||||
|
QQuickItem* settledItem, Qt::Orientations orientations )
|
||||||
{
|
{
|
||||||
if ( baseItem == nullptr || m_attachedItem == nullptr )
|
if ( settledItem == nullptr || m_attachedItem == nullptr )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto anchors = qskGetOrCreateAnchors( m_attachedItem );
|
||||||
|
|
||||||
switch( orientations )
|
switch( orientations )
|
||||||
{
|
{
|
||||||
case Qt::Horizontal:
|
case Qt::Horizontal:
|
||||||
{
|
{
|
||||||
addAnchor( Qt::AnchorLeft, baseItem, Qt::AnchorLeft );
|
clearAnchors();
|
||||||
addAnchor( Qt::AnchorRight, baseItem, Qt::AnchorRight );
|
|
||||||
|
const UpdateBlocker blocker( anchors );
|
||||||
|
addAnchor( Qt::AnchorLeft, settledItem, Qt::AnchorLeft );
|
||||||
|
blocker.reset();
|
||||||
|
|
||||||
|
addAnchor( Qt::AnchorRight, settledItem, Qt::AnchorRight );
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Qt::Vertical:
|
case Qt::Vertical:
|
||||||
{
|
{
|
||||||
addAnchor( Qt::AnchorTop, baseItem, Qt::AnchorTop );
|
clearAnchors();
|
||||||
addAnchor( Qt::AnchorBottom, baseItem, Qt::AnchorBottom );
|
|
||||||
|
const UpdateBlocker blocker( anchors );
|
||||||
|
addAnchor( Qt::AnchorTop, settledItem, Qt::AnchorTop );
|
||||||
|
blocker.reset();
|
||||||
|
|
||||||
|
addAnchor( Qt::AnchorBottom, settledItem, Qt::AnchorBottom );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Qt::Horizontal | Qt::Vertical:
|
case Qt::Horizontal | Qt::Vertical:
|
||||||
{
|
{
|
||||||
auto anchors = qskGetOrCreateAnchors( m_attachedItem );
|
if ( settledItem != anchors->fill() )
|
||||||
for ( int i = 0; i < 6; i++ )
|
|
||||||
{
|
{
|
||||||
const auto& ops = operators( static_cast< Qt::AnchorPoint >( i ) );
|
clearAnchors();
|
||||||
( anchors->*ops.resetLine ) ();
|
anchors->setFill( settledItem );
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors->setFill( baseItem );
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskItemAnchors::setCenterAnchors( QQuickItem* baseItem, Qt::Orientations orientations )
|
void QskItemAnchors::setCenterAnchors(
|
||||||
|
QQuickItem* settledItem, Qt::Orientations orientations )
|
||||||
{
|
{
|
||||||
if ( baseItem == nullptr || m_attachedItem == nullptr )
|
if ( settledItem == nullptr || m_attachedItem == nullptr )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch( orientations )
|
switch( orientations )
|
||||||
{
|
{
|
||||||
case Qt::Horizontal:
|
case Qt::Horizontal:
|
||||||
{
|
{
|
||||||
addAnchor( Qt::AnchorHorizontalCenter, baseItem, Qt::AnchorHorizontalCenter );
|
clearAnchors();
|
||||||
|
addAnchor( Qt::AnchorHorizontalCenter,
|
||||||
|
settledItem, Qt::AnchorHorizontalCenter );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Qt::Vertical:
|
case Qt::Vertical:
|
||||||
{
|
{
|
||||||
addAnchor( Qt::AnchorVerticalCenter, baseItem, Qt::AnchorVerticalCenter );
|
clearAnchors();
|
||||||
|
addAnchor( Qt::AnchorVerticalCenter,
|
||||||
|
settledItem, Qt::AnchorVerticalCenter );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,13 +424,11 @@ void QskItemAnchors::setCenterAnchors( QQuickItem* baseItem, Qt::Orientations or
|
||||||
{
|
{
|
||||||
auto anchors = qskGetOrCreateAnchors( m_attachedItem );
|
auto anchors = qskGetOrCreateAnchors( m_attachedItem );
|
||||||
|
|
||||||
for ( int i = 0; i < 6; i++ )
|
if ( settledItem != anchors->centerIn() )
|
||||||
{
|
{
|
||||||
const auto& ops = operators( static_cast< Qt::AnchorPoint >( i ) );
|
clearAnchors();
|
||||||
( anchors->*ops.resetLine ) ();
|
anchors->setCenterIn( settledItem );
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors->setCenterIn( baseItem );
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,8 +445,8 @@ Qt::AnchorPoint QskItemAnchors::settledItemAnchorPoint( Qt::AnchorPoint edge ) c
|
||||||
we are lying and report Qt::AnchorTop instead. Hm ...
|
we are lying and report Qt::AnchorTop instead. Hm ...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const auto& ops = operators( edge );
|
const auto& ops = qskAnchorLineOperators( edge );
|
||||||
return toAnchorPoint( ( ( anchors->*ops.line ) () ).anchorLine );
|
return qskToAnchorPoint( ( ( anchors->*ops.line ) () ).anchorLine );
|
||||||
}
|
}
|
||||||
|
|
||||||
return Qt::AnchorLeft; // something
|
return Qt::AnchorLeft; // something
|
||||||
|
|
|
@ -29,7 +29,9 @@ class QQuickItem;
|
||||||
of attachedItem only ( conceptually this limitation would not be necessary ).
|
of attachedItem only ( conceptually this limitation would not be necessary ).
|
||||||
|
|
||||||
Note that what is known in QML as "fill" or "centerIn" can be done
|
Note that what is known in QML as "fill" or "centerIn" can be done
|
||||||
using setBorderAnchors or setCenterAnchors.
|
using setBorderAnchors or setCenterAnchors. However the basic layout
|
||||||
|
functionality provided from QskControl::autoLayoutChildren usually
|
||||||
|
offers a more efficient implementation for most situations.
|
||||||
|
|
||||||
Limitations:
|
Limitations:
|
||||||
- access to baseline settings are not implemented
|
- access to baseline settings are not implemented
|
||||||
|
|
Loading…
Reference in New Issue