6#include "QskItemAnchors.h"
10#include <private/qquickanchors_p.h>
11#include <private/qquickanchors_p_p.h>
12#include <private/qquickitem_p.h>
17 struct AnchorLineOperators
19 QQuickAnchorLine ( QQuickAnchors::*line ) () const;
20 void ( QQuickAnchors::*setLine )( const QQuickAnchorLine& );
21 void ( QQuickAnchors::*resetLine )();
27 UpdateBlocker( QQuickAnchors* anchors )
28 : m_anchors( anchors )
30 auto d = QQuickAnchorsPrivate::get( anchors );
32 m_wasComplete = d->componentComplete;
33 d->componentComplete =
false;
43 auto d = QQuickAnchorsPrivate::get( m_anchors );
44 d->componentComplete = m_wasComplete;
47 QQuickAnchors* m_anchors;
52static inline QQuickAnchors* qskGetOrCreateAnchors( QQuickItem* item )
54 if ( item ==
nullptr )
57 return QQuickItemPrivate::get( item )->anchors();
60static inline QQuickAnchors* qskGetAnchors( QQuickItem* item )
62 if ( item ==
nullptr )
65 return QQuickItemPrivate::get( item )->_anchors;
68static inline const QQuickAnchors* qskGetAnchors(
const QQuickItem* item )
70 return qskGetAnchors(
const_cast< QQuickItem*
>( item ) );
73static inline QQuickAnchors::Anchor qskToQuickAnchor( Qt::AnchorPoint edge )
75 using A = QQuickAnchors;
79 case Qt::AnchorLeft:
return A::LeftAnchor;
80 case Qt::AnchorHorizontalCenter:
return A::HCenterAnchor;
81 case Qt::AnchorRight:
return A::RightAnchor;
82 case Qt::AnchorTop:
return A::TopAnchor;
83 case Qt::AnchorVerticalCenter:
return A::VCenterAnchor;
84 case Qt::AnchorBottom:
return A::BottomAnchor;
85 default:
return A::InvalidAnchor;
89static inline Qt::AnchorPoint qskToAnchorPoint( QQuickAnchors::Anchor anchor )
91 using A = QQuickAnchors;
95 case A::LeftAnchor:
return Qt::AnchorLeft;
96 case A::HCenterAnchor:
return Qt::AnchorHorizontalCenter;
97 case A::RightAnchor:
return Qt::AnchorRight;
98 case A::TopAnchor:
return Qt::AnchorTop;
99 case A::VCenterAnchor:
return Qt::AnchorVerticalCenter;
100 case A::BottomAnchor:
return Qt::AnchorBottom;
101 case A::BaselineAnchor:
return Qt::AnchorTop;
102 default:
return Qt::AnchorLeft;
106static inline bool qskIsCenterAnchorPoint( Qt::AnchorPoint edge )
108 return ( edge == Qt::AnchorHorizontalCenter )
109 || ( edge == Qt::AnchorVerticalCenter );
112static inline const AnchorLineOperators& qskAnchorLineOperators( Qt::AnchorPoint edge )
114 using A = QQuickAnchors;
116 static constexpr AnchorLineOperators table[] =
120 { &A::left, &A::setLeft, &A::resetLeft },
121 { &A::horizontalCenter, &A::setHorizontalCenter, &A::resetHorizontalCenter },
122 { &A::right, &A::setRight, &A::resetRight },
123 { &A::top, &A::setTop, &A::resetTop },
124 { &A::verticalCenter, &A::setVerticalCenter, &A::resetVerticalCenter },
125 { &A::bottom, &A::setBottom, &A::resetBottom }
131QskItemAnchors::QskItemAnchors( QQuickItem* attachedItem )
132 : m_attachedItem( attachedItem )
136QskItemAnchors::~QskItemAnchors()
140bool QskItemAnchors::operator==(
const QskItemAnchors& other )
const noexcept
142 return m_attachedItem.data() == other.m_attachedItem.data();
145QQuickItem* QskItemAnchors::attachedItem()
const
147 return m_attachedItem;
150QMarginsF QskItemAnchors::margins()
const
152 const auto anchors = qskGetAnchors( m_attachedItem );
153 if ( anchors ==
nullptr )
156 const auto d = QQuickAnchorsPrivate::get( anchors );
158 const auto left = d->leftMarginExplicit ? d->leftMargin : d->margins;
159 const auto right = d->rightMarginExplicit ? d->rightMargin : d->margins;
160 const auto top = d->rightMarginExplicit ? d->rightMargin : d->margins;
161 const auto bottom = d->bottomMarginExplicit ? d->bottomMargin : d->margins;
163 return QMarginsF( left, top, right, bottom );
166void QskItemAnchors::setMargins(
const QMarginsF& margins )
168 auto anchors = qskGetOrCreateAnchors( m_attachedItem );
169 if ( anchors ==
nullptr )
172 const auto oldMargins = this->margins();
174 Qt::Orientations changes;
176 if ( margins.left() != oldMargins.left() )
177 changes |= Qt::Horizontal;
179 if ( margins.right() != oldMargins.right() )
180 changes |= Qt::Horizontal;
182 if ( margins.top() != oldMargins.top() )
183 changes |= Qt::Vertical;
185 if ( margins.bottom() != oldMargins.bottom() )
186 changes |= Qt::Vertical;
190 const auto left = margins.left();
192 UpdateBlocker blocker( anchors );
194 anchors->setLeftMargin( left + 1.0 );
195 anchors->setRightMargin( margins.right() );
196 anchors->setTopMargin( margins.top() );
197 anchors->setBottomMargin( margins.bottom() );
201 anchors->setLeftMargin( left );
205void QskItemAnchors::setCenterOffsets(
206 qreal horizontalOffset, qreal verticalOffset )
208 if (
auto anchors = qskGetOrCreateAnchors( m_attachedItem ) )
210 anchors->setHorizontalCenterOffset( horizontalOffset );
211 anchors->setVerticalCenterOffset( verticalOffset );
215void QskItemAnchors::setCenterOffset( Qt::Orientation orientation, qreal offset )
217 auto anchors = qskGetOrCreateAnchors( m_attachedItem );
218 if ( anchors ==
nullptr )
221 if ( orientation == Qt::Horizontal )
222 anchors->setHorizontalCenterOffset( offset );
224 anchors->setVerticalCenterOffset( offset );
227qreal QskItemAnchors::centerOffset( Qt::Orientation orientation )
229 if (
const auto anchors = qskGetAnchors( m_attachedItem ) )
231 if ( orientation == Qt::Horizontal )
232 return anchors->horizontalCenterOffset();
234 return anchors->verticalCenterOffset();
240QQuickItem* QskItemAnchors::settledItem( Qt::AnchorPoint edge )
const
242 const auto anchors = qskGetAnchors( m_attachedItem );
243 if ( anchors ==
nullptr )
246 if (
auto fill = anchors->fill() )
247 return !qskIsCenterAnchorPoint( edge ) ? fill :
nullptr;
249 if (
auto centerIn = anchors->centerIn() )
250 return qskIsCenterAnchorPoint( edge ) ? centerIn :
nullptr;
252 const auto& ops = qskAnchorLineOperators( edge );
253 return ( ( anchors->*ops.line ) () ).item;
256void QskItemAnchors::addAnchors( Qt::Corner corner,
257 QQuickItem* settledItem, Qt::Corner settledItemCorner )
260 []( Qt::Corner corner, Qt::Orientation orientation )
262 if ( orientation == Qt::Horizontal )
263 return ( corner & 0x1 ) ? Qt::AnchorRight : Qt::AnchorLeft;
265 return ( corner >= 0x2 ) ? Qt::AnchorBottom : Qt::AnchorTop;
268 addAnchor( anchorPoint( corner, Qt::Horizontal ),
269 settledItem, anchorPoint( settledItemCorner, Qt::Horizontal ) );
271 addAnchor( anchorPoint( corner, Qt::Vertical ),
272 settledItem, anchorPoint( settledItemCorner, Qt::Vertical ) );
275void QskItemAnchors::addAnchor( Qt::AnchorPoint edge, QQuickItem* settledItem,
276 Qt::AnchorPoint settledItemEdge )
278 if ( settledItem ==
nullptr )
281 if (
const auto anchors = qskGetOrCreateAnchors( m_attachedItem ) )
283 const auto& ops = qskAnchorLineOperators( edge );
284 ( anchors->*ops.setLine )( { settledItem, qskToQuickAnchor( settledItemEdge ) } );
288void QskItemAnchors::removeAnchor( Qt::AnchorPoint edge )
290 const auto anchors = qskGetAnchors( m_attachedItem );
291 if ( anchors ==
nullptr )
294 if (
auto fill = anchors->fill() )
296 if ( !qskIsCenterAnchorPoint( edge ) )
298 anchors->resetFill();
301 for (
auto anchorPoint : { Qt::AnchorLeft, Qt::AnchorRight,
302 Qt::AnchorTop, Qt::AnchorBottom } )
304 if ( edge != anchorPoint )
305 addAnchor( anchorPoint, fill, anchorPoint );
312 if (
auto centerIn = anchors->centerIn() )
314 if ( qskIsCenterAnchorPoint( edge ) )
316 anchors->resetCenterIn();
319 const auto otherEdge = ( edge == Qt::AnchorHorizontalCenter )
320 ? Qt::AnchorVerticalCenter : Qt::AnchorHorizontalCenter;
322 addAnchor( otherEdge, centerIn, otherEdge );
328 const auto& ops = qskAnchorLineOperators( edge );
329 ( anchors->*ops.resetLine ) ();
332void QskItemAnchors::clearAnchors()
334 const auto anchors = qskGetAnchors( m_attachedItem );
335 if ( anchors ==
nullptr )
338 const UpdateBlocker blocker( anchors );
340 anchors->resetFill();
341 anchors->resetCenterIn();
343 for (
int i = 0; i < 6; i++ )
345 const auto& ops = qskAnchorLineOperators(
static_cast< Qt::AnchorPoint
>( i ) );
346 ( anchors->*ops.resetLine ) ();
350void QskItemAnchors::setBorderAnchors(
351 QQuickItem* settledItem, Qt::Orientations orientations )
353 if ( settledItem ==
nullptr || m_attachedItem ==
nullptr )
356 auto anchors = qskGetOrCreateAnchors( m_attachedItem );
358 switch( orientations )
364 const UpdateBlocker blocker( anchors );
365 addAnchor( Qt::AnchorLeft, settledItem, Qt::AnchorLeft );
368 addAnchor( Qt::AnchorRight, settledItem, Qt::AnchorRight );
378 const UpdateBlocker blocker( anchors );
379 addAnchor( Qt::AnchorTop, settledItem, Qt::AnchorTop );
382 addAnchor( Qt::AnchorBottom, settledItem, Qt::AnchorBottom );
387 case Qt::Horizontal | Qt::Vertical:
389 if ( settledItem != anchors->fill() )
392 anchors->setFill( settledItem );
399void QskItemAnchors::setCenterAnchors(
400 QQuickItem* settledItem, Qt::Orientations orientations )
402 if ( settledItem ==
nullptr || m_attachedItem ==
nullptr )
405 switch( orientations )
410 addAnchor( Qt::AnchorHorizontalCenter,
411 settledItem, Qt::AnchorHorizontalCenter );
418 addAnchor( Qt::AnchorVerticalCenter,
419 settledItem, Qt::AnchorVerticalCenter );
423 case Qt::Horizontal | Qt::Vertical:
425 auto anchors = qskGetOrCreateAnchors( m_attachedItem );
427 if ( settledItem != anchors->centerIn() )
430 anchors->setCenterIn( settledItem );
437Qt::AnchorPoint QskItemAnchors::settledItemAnchorPoint( Qt::AnchorPoint edge )
const
439 if (
const auto anchors = qskGetAnchors( m_attachedItem ) )
448 const auto& ops = qskAnchorLineOperators( edge );
449 return qskToAnchorPoint( ( ( anchors->*ops.line ) () ).anchorLine );
452 return Qt::AnchorLeft;