2024-10-10 13:55:22 +00:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) The authors
|
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "QskItemAnchors.h"
|
|
|
|
#include "QskMargins.h"
|
|
|
|
|
|
|
|
QSK_QT_PRIVATE_BEGIN
|
|
|
|
#include <private/qquickanchors_p.h>
|
|
|
|
#include <private/qquickanchors_p_p.h>
|
|
|
|
#include <private/qquickitem_p.h>
|
|
|
|
QSK_QT_PRIVATE_END
|
|
|
|
|
|
|
|
QQuickAnchors* qskGetOrCreateAnchors( QQuickItem* item )
|
|
|
|
{
|
|
|
|
if ( item == nullptr )
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
return QQuickItemPrivate::get( item )->anchors();
|
|
|
|
}
|
|
|
|
|
|
|
|
QQuickAnchors* qskGetAnchors( QQuickItem* item )
|
|
|
|
{
|
|
|
|
if ( item == nullptr )
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
return QQuickItemPrivate::get( item )->_anchors;
|
|
|
|
}
|
|
|
|
|
|
|
|
const QQuickAnchors* qskGetAnchors( const QQuickItem* item )
|
|
|
|
{
|
|
|
|
return qskGetAnchors( const_cast< QQuickItem* >( item ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
inline QQuickAnchors::Anchor toQuickAnchor( Qt::AnchorPoint edge )
|
|
|
|
{
|
|
|
|
using A = QQuickAnchors;
|
|
|
|
|
|
|
|
switch( edge )
|
|
|
|
{
|
|
|
|
case Qt::AnchorLeft: return A::LeftAnchor;
|
|
|
|
case Qt::AnchorHorizontalCenter: return A::HCenterAnchor;
|
|
|
|
case Qt::AnchorRight: return A::RightAnchor;
|
|
|
|
case Qt::AnchorTop: return A::TopAnchor;
|
|
|
|
case Qt::AnchorVerticalCenter: return A::VCenterAnchor;
|
|
|
|
case Qt::AnchorBottom: return A::BottomAnchor;
|
|
|
|
default: return A::InvalidAnchor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Qt::AnchorPoint toAnchorPoint( QQuickAnchors::Anchor anchor )
|
|
|
|
{
|
|
|
|
using A = QQuickAnchors;
|
|
|
|
|
|
|
|
switch( anchor )
|
|
|
|
{
|
|
|
|
case A::LeftAnchor: return Qt::AnchorLeft;
|
|
|
|
case A::HCenterAnchor: return Qt::AnchorHorizontalCenter;
|
|
|
|
case A::RightAnchor: return Qt::AnchorRight;
|
|
|
|
case A::TopAnchor: return Qt::AnchorTop;
|
|
|
|
case A::VCenterAnchor: return Qt::AnchorVerticalCenter;
|
|
|
|
case A::BottomAnchor: return Qt::AnchorBottom;
|
|
|
|
case A::BaselineAnchor: return Qt::AnchorTop; // not supported
|
|
|
|
default: return Qt::AnchorLeft;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct AnchorOperators
|
|
|
|
{
|
|
|
|
QQuickAnchorLine ( QQuickAnchors::*line ) () const;
|
|
|
|
void ( QQuickAnchors::*setLine )( const QQuickAnchorLine& );
|
|
|
|
void ( QQuickAnchors::*resetLine )();
|
|
|
|
};
|
|
|
|
|
|
|
|
const AnchorOperators& operators( Qt::AnchorPoint edge )
|
|
|
|
{
|
|
|
|
using A = QQuickAnchors;
|
|
|
|
|
|
|
|
static constexpr AnchorOperators table[] =
|
|
|
|
{
|
|
|
|
// in order of Qt::AnchorPoint
|
|
|
|
|
|
|
|
{ &A::left, &A::setLeft, &A::resetLeft },
|
|
|
|
{ &A::horizontalCenter, &A::setHorizontalCenter, &A::resetHorizontalCenter },
|
|
|
|
{ &A::right, &A::setRight, &A::resetRight },
|
|
|
|
{ &A::top, &A::setTop, &A::resetTop },
|
|
|
|
{ &A::verticalCenter, &A::setVerticalCenter, &A::resetVerticalCenter },
|
|
|
|
{ &A::bottom, &A::setBottom, &A::resetBottom }
|
|
|
|
};
|
|
|
|
|
|
|
|
return table[edge];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-11 06:10:48 +00:00
|
|
|
QskItemAnchors::QskItemAnchors( QQuickItem* attachedItem )
|
|
|
|
: m_attachedItem( attachedItem )
|
2024-10-10 13:55:22 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QskItemAnchors::~QskItemAnchors()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskItemAnchors::operator==( const QskItemAnchors& other ) const noexcept
|
|
|
|
{
|
2024-10-11 06:10:48 +00:00
|
|
|
return m_attachedItem.data() == other.m_attachedItem.data();
|
2024-10-10 13:55:22 +00:00
|
|
|
}
|
|
|
|
|
2024-10-11 06:10:48 +00:00
|
|
|
QQuickItem* QskItemAnchors::attachedItem() const
|
2024-10-10 13:55:22 +00:00
|
|
|
{
|
2024-10-11 06:10:48 +00:00
|
|
|
return m_attachedItem;
|
2024-10-10 13:55:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QMarginsF QskItemAnchors::margins() const
|
|
|
|
{
|
2024-10-11 06:10:48 +00:00
|
|
|
if ( const auto anchors = qskGetAnchors( m_attachedItem ) )
|
2024-10-10 13:55:22 +00:00
|
|
|
{
|
|
|
|
return QMarginsF( anchors->leftMargin(), anchors->topMargin(),
|
|
|
|
anchors->rightMargin(), anchors->bottomMargin() );
|
|
|
|
}
|
|
|
|
|
|
|
|
return QMarginsF();
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskItemAnchors::setMargins( const QMarginsF& margins )
|
|
|
|
{
|
2024-10-11 06:10:48 +00:00
|
|
|
if ( const auto anchors = qskGetOrCreateAnchors( m_attachedItem ) )
|
2024-10-10 13:55:22 +00:00
|
|
|
{
|
|
|
|
anchors->setLeftMargin( margins.left() );
|
|
|
|
anchors->setRightMargin( margins.right() );
|
|
|
|
anchors->setTopMargin( margins.top() );
|
|
|
|
anchors->setBottomMargin( margins.bottom() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskItemAnchors::setCenterOffset( Qt::Orientation orientation, qreal offset )
|
|
|
|
{
|
2024-10-11 06:10:48 +00:00
|
|
|
if ( const auto anchors = qskGetOrCreateAnchors( m_attachedItem ) )
|
2024-10-10 13:55:22 +00:00
|
|
|
{
|
|
|
|
if ( orientation == Qt::Horizontal )
|
|
|
|
anchors->setHorizontalCenterOffset( offset );
|
|
|
|
else
|
|
|
|
anchors->setVerticalCenterOffset( offset );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskItemAnchors::centerOffset( Qt::Orientation orientation )
|
|
|
|
{
|
2024-10-11 06:10:48 +00:00
|
|
|
if ( const auto anchors = qskGetOrCreateAnchors( m_attachedItem ) )
|
2024-10-10 13:55:22 +00:00
|
|
|
{
|
|
|
|
if ( orientation == Qt::Horizontal )
|
|
|
|
return anchors->horizontalCenterOffset();
|
|
|
|
else
|
|
|
|
return anchors->verticalCenterOffset();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskItemAnchors::addAnchors( Qt::Corner corner,
|
|
|
|
QQuickItem* baseItem, Qt::Corner baseCorner )
|
|
|
|
{
|
|
|
|
auto anchorPoint =
|
|
|
|
[]( Qt::Corner corner, Qt::Orientation orientation )
|
|
|
|
{
|
|
|
|
if ( orientation == Qt::Horizontal )
|
|
|
|
return ( corner & 0x1 ) ? Qt::AnchorRight : Qt::AnchorLeft;
|
|
|
|
else
|
|
|
|
return ( corner >= 0x2 ) ? Qt::AnchorBottom : Qt::AnchorTop;
|
|
|
|
};
|
|
|
|
|
|
|
|
addAnchor( anchorPoint( corner, Qt::Horizontal ),
|
|
|
|
baseItem, anchorPoint( baseCorner, Qt::Horizontal ) );
|
|
|
|
|
|
|
|
addAnchor( anchorPoint( corner, Qt::Vertical ),
|
|
|
|
baseItem, anchorPoint( baseCorner, Qt::Vertical ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskItemAnchors::addAnchors( QQuickItem* baseItem, Qt::Orientations orientations )
|
|
|
|
{
|
|
|
|
if ( orientations & Qt::Horizontal )
|
|
|
|
{
|
|
|
|
addAnchor( Qt::AnchorLeft, baseItem, Qt::AnchorLeft );
|
|
|
|
addAnchor( Qt::AnchorRight, baseItem, Qt::AnchorRight );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( orientations & Qt::Vertical )
|
|
|
|
{
|
|
|
|
addAnchor( Qt::AnchorTop, baseItem, Qt::AnchorTop );
|
|
|
|
addAnchor( Qt::AnchorBottom, baseItem, Qt::AnchorBottom );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskItemAnchors::addAnchor( Qt::AnchorPoint edge, QQuickItem* baseItem,
|
|
|
|
Qt::AnchorPoint baseEdge )
|
|
|
|
{
|
2024-10-11 06:10:48 +00:00
|
|
|
if ( const auto anchors = qskGetOrCreateAnchors( m_attachedItem ) )
|
2024-10-10 13:55:22 +00:00
|
|
|
{
|
|
|
|
const auto& ops = operators( edge );
|
|
|
|
( anchors->*ops.setLine )( { baseItem, toQuickAnchor( baseEdge ) } );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskItemAnchors::removeAnchor( Qt::AnchorPoint edge )
|
|
|
|
{
|
2024-10-11 06:10:48 +00:00
|
|
|
if ( const auto anchors = qskGetAnchors( m_attachedItem ) )
|
2024-10-10 13:55:22 +00:00
|
|
|
{
|
|
|
|
const auto& ops = operators( edge );
|
|
|
|
( anchors->*ops.resetLine ) ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QQuickItem* QskItemAnchors::baseItem( Qt::AnchorPoint edge ) const
|
|
|
|
{
|
2024-10-11 06:10:48 +00:00
|
|
|
if ( const auto anchors = qskGetAnchors( m_attachedItem ) )
|
2024-10-10 13:55:22 +00:00
|
|
|
{
|
|
|
|
const auto& ops = operators( edge );
|
|
|
|
return ( ( anchors->*ops.line ) () ).item;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
Qt::AnchorPoint QskItemAnchors::basePosition( Qt::AnchorPoint edge ) const
|
|
|
|
{
|
2024-10-11 06:10:48 +00:00
|
|
|
if ( const auto anchors = qskGetAnchors( m_attachedItem ) )
|
2024-10-10 13:55:22 +00:00
|
|
|
{
|
|
|
|
/*
|
2024-10-11 06:10:48 +00:00
|
|
|
Anchoring to the baseline of the attachedItem might have been
|
2024-10-10 13:55:22 +00:00
|
|
|
done in QML code. As Qt::AnchorPoint does not have a corresponding
|
|
|
|
value for it and QSkinny does not support the baseline concept at all
|
|
|
|
we are lying and report Qt::AnchorTop instead. Hm ...
|
|
|
|
*/
|
|
|
|
|
|
|
|
const auto& ops = operators( edge );
|
|
|
|
return toAnchorPoint( ( ( anchors->*ops.line ) () ).anchorLine );
|
|
|
|
}
|
|
|
|
|
|
|
|
return Qt::AnchorLeft; // something
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskItemAnchors::setControlItem( QQuickItem* item, bool adjustSize )
|
|
|
|
{
|
2024-10-11 06:10:48 +00:00
|
|
|
if ( const auto anchors = qskGetOrCreateAnchors( m_attachedItem ) )
|
2024-10-10 13:55:22 +00:00
|
|
|
{
|
|
|
|
if ( adjustSize )
|
|
|
|
anchors->setFill( item );
|
|
|
|
else
|
|
|
|
anchors->setCenterIn( item );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskItemAnchors::removeControlItem( bool adjustSize )
|
|
|
|
{
|
2024-10-11 06:10:48 +00:00
|
|
|
if ( auto anchors = qskGetAnchors( m_attachedItem ) )
|
2024-10-10 13:55:22 +00:00
|
|
|
{
|
|
|
|
if ( adjustSize )
|
|
|
|
anchors->resetFill();
|
|
|
|
else
|
|
|
|
anchors->resetCenterIn();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QQuickItem* QskItemAnchors::controlItem( bool adjustSize ) const
|
|
|
|
{
|
2024-10-11 06:10:48 +00:00
|
|
|
if ( const auto anchors = qskGetAnchors( m_attachedItem ) )
|
2024-10-10 13:55:22 +00:00
|
|
|
{
|
|
|
|
if ( adjustSize )
|
|
|
|
return anchors->fill();
|
|
|
|
else
|
|
|
|
return anchors->centerIn();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|