1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtQuick module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #include "qquickanchors_p_p.h"
41
42 #include "qquickitem_p.h"
43
44 #include <qqmlinfo.h>
45
46 QT_BEGIN_NAMESPACE
47
readParentItem(const QQuickItem * item)48 static Q_ALWAYS_INLINE QQuickItem *readParentItem(const QQuickItem *item)
49 {
50 return QQuickItemPrivate::get(item)->parentItem;
51 }
52
readX(const QQuickItem * item)53 static Q_ALWAYS_INLINE qreal readX(const QQuickItem *item)
54 {
55 return QQuickItemPrivate::get(item)->x;
56 }
57
readY(const QQuickItem * item)58 static Q_ALWAYS_INLINE qreal readY(const QQuickItem *item)
59 {
60 return QQuickItemPrivate::get(item)->y;
61 }
62
readWidth(const QQuickItem * item)63 static Q_ALWAYS_INLINE qreal readWidth(const QQuickItem *item)
64 {
65 return QQuickItemPrivate::get(item)->width;
66 }
67
readHeight(const QQuickItem * item)68 static Q_ALWAYS_INLINE qreal readHeight(const QQuickItem *item)
69 {
70 return QQuickItemPrivate::get(item)->height;
71 }
72
readBaselineOffset(const QQuickItem * item)73 static Q_ALWAYS_INLINE qreal readBaselineOffset(const QQuickItem *item)
74 {
75 return QQuickItemPrivate::get(item)->baselineOffset;
76 }
77
78 //TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
79 //TODO: support non-parent, non-sibling (need to find lowest common ancestor)
80
hcenter(const QQuickItem * item)81 static inline qreal hcenter(const QQuickItem *item)
82 {
83 qreal width = readWidth(item);
84 if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) {
85 if (!QQuickAnchorsPrivate::get(anchors)->centerAligned)
86 return width / 2;
87 }
88 int iw = width;
89 if (iw % 2)
90 return (width + 1) / 2;
91 else
92 return width / 2;
93 }
94
vcenter(const QQuickItem * item)95 static inline qreal vcenter(const QQuickItem *item)
96 {
97 qreal height = readHeight(item);
98 if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) {
99 if (!QQuickAnchorsPrivate::get(anchors)->centerAligned)
100 return height / 2;
101 }
102 int ih = height;
103 if (ih % 2)
104 return (height + 1) / 2;
105 else
106 return height / 2;
107 }
108
109 //local position
position(const QQuickItem * item,QQuickAnchors::Anchor anchorLine)110 static inline qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
111 {
112 qreal ret = 0.0;
113 switch (anchorLine) {
114 case QQuickAnchors::LeftAnchor:
115 ret = readX(item);
116 break;
117 case QQuickAnchors::RightAnchor:
118 ret = readX(item) + readWidth(item);
119 break;
120 case QQuickAnchors::TopAnchor:
121 ret = readY(item);
122 break;
123 case QQuickAnchors::BottomAnchor:
124 ret = readY(item) + readHeight(item);
125 break;
126 case QQuickAnchors::HCenterAnchor:
127 ret = readX(item) + hcenter(item);
128 break;
129 case QQuickAnchors::VCenterAnchor:
130 ret = readY(item) + vcenter(item);
131 break;
132 case QQuickAnchors::BaselineAnchor:
133 ret = readY(item) + readBaselineOffset(item);
134 break;
135 default:
136 break;
137 }
138
139 return ret;
140 }
141
142 //position when origin is 0,0
adjustedPosition(QQuickItem * item,QQuickAnchors::Anchor anchorLine)143 static inline qreal adjustedPosition(QQuickItem *item, QQuickAnchors::Anchor anchorLine)
144 {
145 qreal ret = 0.0;
146 switch (anchorLine) {
147 case QQuickAnchors::LeftAnchor:
148 ret = 0.0;
149 break;
150 case QQuickAnchors::RightAnchor:
151 ret = readWidth(item);
152 break;
153 case QQuickAnchors::TopAnchor:
154 ret = 0.0;
155 break;
156 case QQuickAnchors::BottomAnchor:
157 ret = readHeight(item);
158 break;
159 case QQuickAnchors::HCenterAnchor:
160 ret = hcenter(item);
161 break;
162 case QQuickAnchors::VCenterAnchor:
163 ret = vcenter(item);
164 break;
165 case QQuickAnchors::BaselineAnchor:
166 ret = readBaselineOffset(item);
167 break;
168 default:
169 break;
170 }
171
172 return ret;
173 }
174
QQuickAnchors(QQuickItem * item,QObject * parent)175 QQuickAnchors::QQuickAnchors(QQuickItem *item, QObject *parent)
176 : QObject(*new QQuickAnchorsPrivate(item), parent)
177 {
178 }
179
~QQuickAnchors()180 QQuickAnchors::~QQuickAnchors()
181 {
182 Q_D(QQuickAnchors);
183 d->inDestructor = true;
184 d->remDepend(d->fill);
185 d->remDepend(d->centerIn);
186 d->remDepend(d->leftAnchorItem);
187 d->remDepend(d->rightAnchorItem);
188 d->remDepend(d->topAnchorItem);
189 d->remDepend(d->bottomAnchorItem);
190 d->remDepend(d->vCenterAnchorItem);
191 d->remDepend(d->hCenterAnchorItem);
192 d->remDepend(d->baselineAnchorItem);
193 }
194
fillChanged()195 void QQuickAnchorsPrivate::fillChanged()
196 {
197 Q_Q(QQuickAnchors);
198 if (!fill || !isItemComplete())
199 return;
200
201 if (updatingFill < 2) {
202 ++updatingFill;
203
204 qreal horizontalMargin = q->mirrored() ? rightMargin : leftMargin;
205
206 if (fill == readParentItem(item)) { //child-parent
207 setItemPos(QPointF(horizontalMargin, topMargin));
208 } else if (readParentItem(fill) == readParentItem(item)) { //siblings
209 setItemPos(QPointF(readX(fill)+horizontalMargin, readY(fill) + topMargin));
210 }
211 setItemSize(QSizeF(readWidth(fill) - leftMargin - rightMargin,
212 readHeight(fill) - topMargin - bottomMargin));
213
214 --updatingFill;
215 } else {
216 // ### Make this certain :)
217 qmlWarning(item) << QQuickAnchors::tr("Possible anchor loop detected on fill.");
218 }
219
220 }
221
centerInChanged()222 void QQuickAnchorsPrivate::centerInChanged()
223 {
224 Q_Q(QQuickAnchors);
225 if (!centerIn || fill || !isItemComplete())
226 return;
227
228 if (updatingCenterIn < 2) {
229 ++updatingCenterIn;
230
231 qreal effectiveHCenterOffset = q->mirrored() ? -hCenterOffset : hCenterOffset;
232 if (centerIn == readParentItem(item)) {
233 QPointF p(hcenter(readParentItem(item)) - hcenter(item) + effectiveHCenterOffset,
234 vcenter(readParentItem(item)) - vcenter(item) + vCenterOffset);
235 setItemPos(p);
236
237 } else if (readParentItem(centerIn) == readParentItem(item)) {
238 QPointF p(centerIn->x() + hcenter(centerIn) - hcenter(item) + effectiveHCenterOffset,
239 centerIn->y() + vcenter(centerIn) - vcenter(item) + vCenterOffset);
240 setItemPos(p);
241 }
242
243 --updatingCenterIn;
244 } else {
245 // ### Make this certain :)
246 qmlWarning(item) << QQuickAnchors::tr("Possible anchor loop detected on centerIn.");
247 }
248 }
249
clearItem(QQuickItem * item)250 void QQuickAnchorsPrivate::clearItem(QQuickItem *item)
251 {
252 if (!item)
253 return;
254 if (fill == item)
255 fill = nullptr;
256 if (centerIn == item)
257 centerIn = nullptr;
258 if (leftAnchorItem == item) {
259 leftAnchorItem = nullptr;
260 usedAnchors &= ~QQuickAnchors::LeftAnchor;
261 }
262 if (rightAnchorItem == item) {
263 rightAnchorItem = nullptr;
264 usedAnchors &= ~QQuickAnchors::RightAnchor;
265 }
266 if (topAnchorItem == item) {
267 topAnchorItem = nullptr;
268 usedAnchors &= ~QQuickAnchors::TopAnchor;
269 }
270 if (bottomAnchorItem == item) {
271 bottomAnchorItem = nullptr;
272 usedAnchors &= ~QQuickAnchors::BottomAnchor;
273 }
274 if (vCenterAnchorItem == item) {
275 vCenterAnchorItem = nullptr;
276 usedAnchors &= ~QQuickAnchors::VCenterAnchor;
277 }
278 if (hCenterAnchorItem == item) {
279 hCenterAnchorItem = nullptr;
280 usedAnchors &= ~QQuickAnchors::HCenterAnchor;
281 }
282 if (baselineAnchorItem == item) {
283 baselineAnchorItem = nullptr;
284 usedAnchors &= ~QQuickAnchors::BaselineAnchor;
285 }
286 }
287
calculateDependency(QQuickItem * controlItem) const288 QQuickGeometryChange QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) const
289 {
290 QQuickGeometryChange dependency;
291
292 if (!controlItem || inDestructor)
293 return dependency;
294
295 if (fill == controlItem) {
296 if (controlItem == readParentItem(item))
297 dependency.setSizeChange(true);
298 else //sibling
299 dependency.setAllChanged(true);
300 return dependency; //exit early
301 }
302
303 if (centerIn == controlItem) {
304 if (controlItem == readParentItem(item))
305 dependency.setSizeChange(true);
306 else //sibling
307 dependency.setAllChanged(true);
308 return dependency; //exit early
309 }
310
311 if ((usedAnchors & QQuickAnchors::LeftAnchor && leftAnchorItem == controlItem) ||
312 (usedAnchors & QQuickAnchors::RightAnchor && rightAnchorItem == controlItem) ||
313 (usedAnchors & QQuickAnchors::HCenterAnchor && hCenterAnchorItem == controlItem)) {
314 if (controlItem == readParentItem(item))
315 dependency.setWidthChange(true);
316 else //sibling
317 dependency.setHorizontalChange(true);
318 }
319
320 if ((usedAnchors & QQuickAnchors::TopAnchor && topAnchorItem == controlItem) ||
321 (usedAnchors & QQuickAnchors::BottomAnchor && bottomAnchorItem == controlItem) ||
322 (usedAnchors & QQuickAnchors::VCenterAnchor && vCenterAnchorItem == controlItem) ||
323 (usedAnchors & QQuickAnchors::BaselineAnchor && baselineAnchorItem == controlItem)) {
324 if (controlItem == readParentItem(item))
325 dependency.setHeightChange(true);
326 else //sibling
327 dependency.setVerticalChange(true);
328 }
329
330 return dependency;
331 }
332
addDepend(QQuickItem * item)333 void QQuickAnchorsPrivate::addDepend(QQuickItem *item)
334 {
335 if (!item || !componentComplete)
336 return;
337
338 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
339 p->updateOrAddGeometryChangeListener(this, calculateDependency(item));
340 }
341
remDepend(QQuickItem * item)342 void QQuickAnchorsPrivate::remDepend(QQuickItem *item)
343 {
344 if (!item || !componentComplete)
345 return;
346
347 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
348 p->updateOrRemoveGeometryChangeListener(this, calculateDependency(item));
349 }
350
mirrored()351 bool QQuickAnchors::mirrored()
352 {
353 Q_D(QQuickAnchors);
354 return QQuickItemPrivate::get(d->item)->effectiveLayoutMirror;
355 }
356
alignWhenCentered() const357 bool QQuickAnchors::alignWhenCentered() const
358 {
359 Q_D(const QQuickAnchors);
360 return d->centerAligned;
361 }
362
setAlignWhenCentered(bool aligned)363 void QQuickAnchors::setAlignWhenCentered(bool aligned)
364 {
365 Q_D(QQuickAnchors);
366 if (aligned == d->centerAligned)
367 return;
368 d->centerAligned = aligned;
369 emit centerAlignedChanged();
370 if (d->centerIn) {
371 d->centerInChanged();
372 } else {
373 if (d->usedAnchors & QQuickAnchors::VCenterAnchor)
374 d->updateVerticalAnchors();
375 else if (d->usedAnchors & QQuickAnchors::HCenterAnchor)
376 d->updateHorizontalAnchors();
377 }
378 }
379
isItemComplete() const380 bool QQuickAnchorsPrivate::isItemComplete() const
381 {
382 return componentComplete;
383 }
384
classBegin()385 void QQuickAnchors::classBegin()
386 {
387 Q_D(QQuickAnchors);
388 d->componentComplete = false;
389 }
390
componentComplete()391 void QQuickAnchors::componentComplete()
392 {
393 Q_D(QQuickAnchors);
394 d->componentComplete = true;
395 }
396
setItemHeight(qreal v)397 void QQuickAnchorsPrivate::setItemHeight(qreal v)
398 {
399 updatingMe = true;
400 item->setHeight(v);
401 updatingMe = false;
402 }
403
setItemWidth(qreal v)404 void QQuickAnchorsPrivate::setItemWidth(qreal v)
405 {
406 updatingMe = true;
407 item->setWidth(v);
408 updatingMe = false;
409 }
410
setItemX(qreal v)411 void QQuickAnchorsPrivate::setItemX(qreal v)
412 {
413 updatingMe = true;
414 item->setX(v);
415 updatingMe = false;
416 }
417
setItemY(qreal v)418 void QQuickAnchorsPrivate::setItemY(qreal v)
419 {
420 updatingMe = true;
421 item->setY(v);
422 updatingMe = false;
423 }
424
setItemPos(const QPointF & v)425 void QQuickAnchorsPrivate::setItemPos(const QPointF &v)
426 {
427 updatingMe = true;
428 item->setPosition(v);
429 updatingMe = false;
430 }
431
setItemSize(const QSizeF & v)432 void QQuickAnchorsPrivate::setItemSize(const QSizeF &v)
433 {
434 updatingMe = true;
435 item->setSize(v);
436 updatingMe = false;
437 }
438
updateMe()439 void QQuickAnchorsPrivate::updateMe()
440 {
441 if (updatingMe) {
442 updatingMe = false;
443 return;
444 }
445
446 update();
447 }
448
updateOnComplete()449 void QQuickAnchorsPrivate::updateOnComplete()
450 {
451 //optimization to only set initial dependencies once, at completion time
452 QQuickItem *dependencies[9];
453 dependencies[0] = fill;
454 dependencies[1] = centerIn;
455 dependencies[2] = leftAnchorItem;
456 dependencies[3] = rightAnchorItem;
457 dependencies[4] = hCenterAnchorItem;
458 dependencies[5] = topAnchorItem;
459 dependencies[6] = bottomAnchorItem;
460 dependencies[7] = vCenterAnchorItem;
461 dependencies[8] = baselineAnchorItem;
462
463 std::sort(dependencies, dependencies + 9);
464
465 QQuickItem *lastDependency = nullptr;
466 for (int i = 0; i < 9; ++i) {
467 QQuickItem *dependency = dependencies[i];
468 if (lastDependency != dependency) {
469 addDepend(dependency);
470 lastDependency = dependency;
471 }
472 }
473
474 update();
475 }
476
477
update()478 void QQuickAnchorsPrivate::update()
479 {
480 if (!isItemComplete())
481 return;
482
483 if (fill) {
484 fillChanged();
485 } else if (centerIn) {
486 centerInChanged();
487 } else {
488 if (usedAnchors & QQuickAnchors::Horizontal_Mask)
489 updateHorizontalAnchors();
490 if (usedAnchors & QQuickAnchors::Vertical_Mask)
491 updateVerticalAnchors();
492 }
493 }
494
itemGeometryChanged(QQuickItem *,QQuickGeometryChange change,const QRectF &)495 void QQuickAnchorsPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange change, const QRectF &)
496 {
497 if (!isItemComplete())
498 return;
499
500 if (fill) {
501 fillChanged();
502 } else if (centerIn) {
503 centerInChanged();
504 } else {
505 if ((usedAnchors & QQuickAnchors::Horizontal_Mask) && change.horizontalChange())
506 updateHorizontalAnchors();
507 if ((usedAnchors & QQuickAnchors::Vertical_Mask) && change.verticalChange())
508 updateVerticalAnchors();
509 }
510 }
511
fill() const512 QQuickItem *QQuickAnchors::fill() const
513 {
514 Q_D(const QQuickAnchors);
515 return d->fill;
516 }
517
setFill(QQuickItem * f)518 void QQuickAnchors::setFill(QQuickItem *f)
519 {
520 Q_D(QQuickAnchors);
521 if (d->fill == f)
522 return;
523
524 if (!f) {
525 QQuickItem *oldFill = d->fill;
526 d->fill = f;
527 d->remDepend(oldFill);
528 emit fillChanged();
529 return;
530 }
531 if (f != readParentItem(d->item) && readParentItem(f) != readParentItem(d->item)){
532 qmlWarning(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
533 return;
534 }
535 QQuickItem *oldFill = d->fill;
536 d->fill = f;
537 d->remDepend(oldFill);
538 d->addDepend(d->fill);
539 emit fillChanged();
540 d->fillChanged();
541 }
542
resetFill()543 void QQuickAnchors::resetFill()
544 {
545 setFill(nullptr);
546 }
547
centerIn() const548 QQuickItem *QQuickAnchors::centerIn() const
549 {
550 Q_D(const QQuickAnchors);
551 return d->centerIn;
552 }
553
setCenterIn(QQuickItem * c)554 void QQuickAnchors::setCenterIn(QQuickItem* c)
555 {
556 Q_D(QQuickAnchors);
557 if (d->centerIn == c)
558 return;
559
560 if (!c) {
561 QQuickItem *oldCI = d->centerIn;
562 d->centerIn = c;
563 d->remDepend(oldCI);
564 emit centerInChanged();
565 return;
566 }
567 if (c != readParentItem(d->item) && readParentItem(c) != readParentItem(d->item)){
568 qmlWarning(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
569 return;
570 }
571 QQuickItem *oldCI = d->centerIn;
572 d->centerIn = c;
573 d->remDepend(oldCI);
574 d->addDepend(d->centerIn);
575 emit centerInChanged();
576 d->centerInChanged();
577 }
578
resetCenterIn()579 void QQuickAnchors::resetCenterIn()
580 {
581 setCenterIn(nullptr);
582 }
583
calcStretch(QQuickItem * edge1Item,QQuickAnchors::Anchor edge1Line,QQuickItem * edge2Item,QQuickAnchors::Anchor edge2Line,qreal offset1,qreal offset2,QQuickAnchors::Anchor line,qreal & stretch) const584 bool QQuickAnchorsPrivate::calcStretch(QQuickItem *edge1Item,
585 QQuickAnchors::Anchor edge1Line,
586 QQuickItem *edge2Item,
587 QQuickAnchors::Anchor edge2Line,
588 qreal offset1,
589 qreal offset2,
590 QQuickAnchors::Anchor line,
591 qreal &stretch) const
592 {
593 bool edge1IsParent = (edge1Item == readParentItem(item));
594 bool edge2IsParent = (edge2Item == readParentItem(item));
595 bool edge1IsSibling = (readParentItem(edge1Item) == readParentItem(item));
596 bool edge2IsSibling = (readParentItem(edge2Item) == readParentItem(item));
597
598 bool invalid = false;
599 if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
600 stretch = (position(edge2Item, edge2Line) + offset2)
601 - (position(edge1Item, edge1Line) + offset1);
602 } else if (edge2IsParent && edge1IsSibling) {
603 stretch = (position(edge2Item, edge2Line) + offset2)
604 - (position(readParentItem(item), line)
605 + position(edge1Item, edge1Line) + offset1);
606 } else if (edge2IsSibling && edge1IsParent) {
607 stretch = (position(readParentItem(item), line) + position(edge2Item, edge2Line) + offset2)
608 - (position(edge1Item, edge1Line) + offset1);
609 } else
610 invalid = true;
611
612 return invalid;
613 }
614
updateVerticalAnchors()615 void QQuickAnchorsPrivate::updateVerticalAnchors()
616 {
617 if (fill || centerIn || !isItemComplete())
618 return;
619
620 if (Q_UNLIKELY(updatingVerticalAnchor > 1)) {
621 // ### Make this certain :)
622 qmlWarning(item) << QQuickAnchors::tr("Possible anchor loop detected on vertical anchor.");
623 return;
624 }
625
626 ++updatingVerticalAnchor;
627 if (usedAnchors & QQuickAnchors::TopAnchor) {
628 //Handle stretching
629 bool invalid = true;
630 qreal height = 0.0;
631 if (usedAnchors & QQuickAnchors::BottomAnchor) {
632 invalid = calcStretch(topAnchorItem, topAnchorLine,
633 bottomAnchorItem, bottomAnchorLine,
634 topMargin, -bottomMargin, QQuickAnchors::TopAnchor, height);
635 } else if (usedAnchors & QQuickAnchors::VCenterAnchor) {
636 invalid = calcStretch(topAnchorItem, topAnchorLine,
637 vCenterAnchorItem, vCenterAnchorLine,
638 topMargin, vCenterOffset, QQuickAnchors::TopAnchor, height);
639 height *= 2;
640 }
641 if (!invalid)
642 setItemHeight(height);
643
644 //Handle top
645 if (topAnchorItem == readParentItem(item)) {
646 setItemY(adjustedPosition(topAnchorItem, topAnchorLine) + topMargin);
647 } else if (readParentItem(topAnchorItem) == readParentItem(item)) {
648 setItemY(position(topAnchorItem, topAnchorLine) + topMargin);
649 }
650 } else if (usedAnchors & QQuickAnchors::BottomAnchor) {
651 //Handle stretching (top + bottom case is handled above)
652 if (usedAnchors & QQuickAnchors::VCenterAnchor) {
653 qreal height = 0.0;
654 bool invalid = calcStretch(vCenterAnchorItem, vCenterAnchorLine,
655 bottomAnchorItem, bottomAnchorLine,
656 vCenterOffset, -bottomMargin, QQuickAnchors::TopAnchor,
657 height);
658 if (!invalid)
659 setItemHeight(height*2);
660 }
661
662 //Handle bottom
663 if (bottomAnchorItem == readParentItem(item)) {
664 setItemY(adjustedPosition(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin);
665 } else if (readParentItem(bottomAnchorItem) == readParentItem(item)) {
666 setItemY(position(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin);
667 }
668 } else if (usedAnchors & QQuickAnchors::VCenterAnchor) {
669 //(stetching handled above)
670
671 //Handle vCenter
672 if (vCenterAnchorItem == readParentItem(item)) {
673 setItemY(adjustedPosition(vCenterAnchorItem, vCenterAnchorLine)
674 - vcenter(item) + vCenterOffset);
675 } else if (readParentItem(vCenterAnchorItem) == readParentItem(item)) {
676 setItemY(position(vCenterAnchorItem, vCenterAnchorLine) - vcenter(item) + vCenterOffset);
677 }
678 } else if (usedAnchors & QQuickAnchors::BaselineAnchor) {
679 //Handle baseline
680 if (baselineAnchorItem == readParentItem(item)) {
681 setItemY(adjustedPosition(baselineAnchorItem, baselineAnchorLine)
682 - readBaselineOffset(item) + baselineOffset);
683 } else if (readParentItem(baselineAnchorItem) == readParentItem(item)) {
684 setItemY(position(baselineAnchorItem, baselineAnchorLine)
685 - readBaselineOffset(item) + baselineOffset);
686 }
687 }
688 --updatingVerticalAnchor;
689 }
690
reverseAnchorLine(QQuickAnchors::Anchor anchorLine)691 static inline QQuickAnchors::Anchor reverseAnchorLine(QQuickAnchors::Anchor anchorLine)
692 {
693 if (anchorLine == QQuickAnchors::LeftAnchor) {
694 return QQuickAnchors::RightAnchor;
695 } else if (anchorLine == QQuickAnchors::RightAnchor) {
696 return QQuickAnchors::LeftAnchor;
697 } else {
698 return anchorLine;
699 }
700 }
701
updateHorizontalAnchors()702 void QQuickAnchorsPrivate::updateHorizontalAnchors()
703 {
704 Q_Q(QQuickAnchors);
705 if (fill || centerIn || !isItemComplete())
706 return;
707
708 if (updatingHorizontalAnchor < 3) {
709 ++updatingHorizontalAnchor;
710 qreal effectiveRightMargin, effectiveLeftMargin, effectiveHorizontalCenterOffset;
711 QQuickItem *effectiveLeftItem, *effectiveRightItem, *effectiveHorizontalCenterItem;
712 QQuickAnchors::Anchor effectiveLeftLine, effectiveRightLine, effectiveHorizontalCenterLine;
713 QQuickAnchors::Anchor effectiveLeftAnchor, effectiveRightAnchor;
714 if (q->mirrored()) {
715 effectiveLeftAnchor = QQuickAnchors::RightAnchor;
716 effectiveRightAnchor = QQuickAnchors::LeftAnchor;
717 effectiveLeftItem = rightAnchorItem;
718 effectiveLeftLine = reverseAnchorLine(rightAnchorLine);
719 effectiveRightItem = leftAnchorItem;
720 effectiveRightLine = reverseAnchorLine(leftAnchorLine);
721 effectiveHorizontalCenterItem = hCenterAnchorItem;
722 effectiveHorizontalCenterLine = reverseAnchorLine(hCenterAnchorLine);
723 effectiveLeftMargin = rightMargin;
724 effectiveRightMargin = leftMargin;
725 effectiveHorizontalCenterOffset = -hCenterOffset;
726 } else {
727 effectiveLeftAnchor = QQuickAnchors::LeftAnchor;
728 effectiveRightAnchor = QQuickAnchors::RightAnchor;
729 effectiveLeftItem = leftAnchorItem;
730 effectiveLeftLine = leftAnchorLine;
731 effectiveRightItem = rightAnchorItem;
732 effectiveRightLine = rightAnchorLine;
733 effectiveHorizontalCenterItem = hCenterAnchorItem;
734 effectiveHorizontalCenterLine = hCenterAnchorLine;
735 effectiveLeftMargin = leftMargin;
736 effectiveRightMargin = rightMargin;
737 effectiveHorizontalCenterOffset = hCenterOffset;
738 }
739
740 if (usedAnchors & effectiveLeftAnchor) {
741 //Handle stretching
742 bool invalid = true;
743 qreal width = 0.0;
744 if (usedAnchors & effectiveRightAnchor) {
745 invalid = calcStretch(effectiveLeftItem, effectiveLeftLine,
746 effectiveRightItem, effectiveRightLine,
747 effectiveLeftMargin, -effectiveRightMargin,
748 QQuickAnchors::LeftAnchor, width);
749 } else if (usedAnchors & QQuickAnchors::HCenterAnchor) {
750 invalid = calcStretch(effectiveLeftItem, effectiveLeftLine,
751 effectiveHorizontalCenterItem, effectiveHorizontalCenterLine,
752 effectiveLeftMargin, effectiveHorizontalCenterOffset,
753 QQuickAnchors::LeftAnchor, width);
754 width *= 2;
755 }
756 if (!invalid)
757 setItemWidth(width);
758
759 //Handle left
760 if (effectiveLeftItem == readParentItem(item)) {
761 setItemX(adjustedPosition(effectiveLeftItem, effectiveLeftLine) + effectiveLeftMargin);
762 } else if (readParentItem(effectiveLeftItem) == readParentItem(item)) {
763 setItemX(position(effectiveLeftItem, effectiveLeftLine) + effectiveLeftMargin);
764 }
765 } else if (usedAnchors & effectiveRightAnchor) {
766 //Handle stretching (left + right case is handled in updateLeftAnchor)
767 if (usedAnchors & QQuickAnchors::HCenterAnchor) {
768 qreal width = 0.0;
769 bool invalid = calcStretch(effectiveHorizontalCenterItem,
770 effectiveHorizontalCenterLine,
771 effectiveRightItem, effectiveRightLine,
772 effectiveHorizontalCenterOffset, -effectiveRightMargin,
773 QQuickAnchors::LeftAnchor, width);
774 if (!invalid)
775 setItemWidth(width*2);
776 }
777
778 //Handle right
779 if (effectiveRightItem == readParentItem(item)) {
780 setItemX(adjustedPosition(effectiveRightItem, effectiveRightLine)
781 - readWidth(item) - effectiveRightMargin);
782 } else if (readParentItem(effectiveRightItem) == readParentItem(item)) {
783 setItemX(position(effectiveRightItem, effectiveRightLine)
784 - readWidth(item) - effectiveRightMargin);
785 }
786 } else if (usedAnchors & QQuickAnchors::HCenterAnchor) {
787 //Handle hCenter
788 if (effectiveHorizontalCenterItem == readParentItem(item)) {
789 setItemX(adjustedPosition(effectiveHorizontalCenterItem, effectiveHorizontalCenterLine) - hcenter(item) + effectiveHorizontalCenterOffset);
790 } else if (readParentItem(effectiveHorizontalCenterItem) == readParentItem(item)) {
791 setItemX(position(effectiveHorizontalCenterItem, effectiveHorizontalCenterLine) - hcenter(item) + effectiveHorizontalCenterOffset);
792 }
793 }
794 --updatingHorizontalAnchor;
795 } else {
796 // ### Make this certain :)
797 qmlWarning(item) << QQuickAnchors::tr("Possible anchor loop detected on horizontal anchor.");
798 }
799 }
800
top() const801 QQuickAnchorLine QQuickAnchors::top() const
802 {
803 Q_D(const QQuickAnchors);
804 return QQuickAnchorLine(d->topAnchorItem, d->topAnchorLine);
805 }
806
setTop(const QQuickAnchorLine & edge)807 void QQuickAnchors::setTop(const QQuickAnchorLine &edge)
808 {
809 Q_D(QQuickAnchors);
810 if (!d->checkVAnchorValid(edge) ||
811 (d->topAnchorItem == edge.item && d->topAnchorLine == edge.anchorLine))
812 return;
813
814 d->usedAnchors |= TopAnchor;
815
816 if (!d->checkVValid()) {
817 d->usedAnchors &= ~TopAnchor;
818 return;
819 }
820
821 QQuickItem *oldTop = d->topAnchorItem;
822 d->topAnchorItem = edge.item;
823 d->topAnchorLine = edge.anchorLine;
824 d->remDepend(oldTop);
825 d->addDepend(d->topAnchorItem);
826 emit topChanged();
827 d->updateVerticalAnchors();
828 }
829
resetTop()830 void QQuickAnchors::resetTop()
831 {
832 Q_D(QQuickAnchors);
833 d->usedAnchors &= ~TopAnchor;
834 d->remDepend(d->topAnchorItem);
835 d->topAnchorItem = nullptr;
836 d->topAnchorLine = QQuickAnchors::InvalidAnchor;
837 emit topChanged();
838 d->updateVerticalAnchors();
839 }
840
bottom() const841 QQuickAnchorLine QQuickAnchors::bottom() const
842 {
843 Q_D(const QQuickAnchors);
844 return QQuickAnchorLine(d->bottomAnchorItem, d->bottomAnchorLine);
845 }
846
setBottom(const QQuickAnchorLine & edge)847 void QQuickAnchors::setBottom(const QQuickAnchorLine &edge)
848 {
849 Q_D(QQuickAnchors);
850 if (!d->checkVAnchorValid(edge) ||
851 (d->bottomAnchorItem == edge.item && d->bottomAnchorLine == edge.anchorLine))
852 return;
853
854 d->usedAnchors |= BottomAnchor;
855
856 if (!d->checkVValid()) {
857 d->usedAnchors &= ~BottomAnchor;
858 return;
859 }
860
861 QQuickItem *oldBottom = d->bottomAnchorItem;
862 d->bottomAnchorItem = edge.item;
863 d->bottomAnchorLine = edge.anchorLine;
864 d->remDepend(oldBottom);
865 d->addDepend(d->bottomAnchorItem);
866 emit bottomChanged();
867 d->updateVerticalAnchors();
868 }
869
resetBottom()870 void QQuickAnchors::resetBottom()
871 {
872 Q_D(QQuickAnchors);
873 d->usedAnchors &= ~BottomAnchor;
874 d->remDepend(d->bottomAnchorItem);
875 d->bottomAnchorItem = nullptr;
876 d->bottomAnchorLine = QQuickAnchors::InvalidAnchor;
877 emit bottomChanged();
878 d->updateVerticalAnchors();
879 }
880
verticalCenter() const881 QQuickAnchorLine QQuickAnchors::verticalCenter() const
882 {
883 Q_D(const QQuickAnchors);
884 return QQuickAnchorLine(d->vCenterAnchorItem, d->vCenterAnchorLine);
885 }
886
setVerticalCenter(const QQuickAnchorLine & edge)887 void QQuickAnchors::setVerticalCenter(const QQuickAnchorLine &edge)
888 {
889 Q_D(QQuickAnchors);
890 if (!d->checkVAnchorValid(edge) ||
891 (d->vCenterAnchorItem == edge.item && d->vCenterAnchorLine == edge.anchorLine))
892 return;
893
894 d->usedAnchors |= VCenterAnchor;
895
896 if (!d->checkVValid()) {
897 d->usedAnchors &= ~VCenterAnchor;
898 return;
899 }
900
901 QQuickItem *oldVCenter = d->vCenterAnchorItem;
902 d->vCenterAnchorItem = edge.item;
903 d->vCenterAnchorLine = edge.anchorLine;
904 d->remDepend(oldVCenter);
905 d->addDepend(d->vCenterAnchorItem);
906 emit verticalCenterChanged();
907 d->updateVerticalAnchors();
908 }
909
resetVerticalCenter()910 void QQuickAnchors::resetVerticalCenter()
911 {
912 Q_D(QQuickAnchors);
913 d->usedAnchors &= ~VCenterAnchor;
914 d->remDepend(d->vCenterAnchorItem);
915 d->vCenterAnchorItem = nullptr;
916 d->vCenterAnchorLine = QQuickAnchors::InvalidAnchor;
917 emit verticalCenterChanged();
918 d->updateVerticalAnchors();
919 }
920
baseline() const921 QQuickAnchorLine QQuickAnchors::baseline() const
922 {
923 Q_D(const QQuickAnchors);
924 return QQuickAnchorLine(d->baselineAnchorItem, d->baselineAnchorLine);
925 }
926
setBaseline(const QQuickAnchorLine & edge)927 void QQuickAnchors::setBaseline(const QQuickAnchorLine &edge)
928 {
929 Q_D(QQuickAnchors);
930 if (!d->checkVAnchorValid(edge) ||
931 (d->baselineAnchorItem == edge.item && d->baselineAnchorLine == edge.anchorLine))
932 return;
933
934 d->usedAnchors |= BaselineAnchor;
935
936 if (!d->checkVValid()) {
937 d->usedAnchors &= ~BaselineAnchor;
938 return;
939 }
940
941 QQuickItem *oldBaseline = d->baselineAnchorItem;
942 d->baselineAnchorItem = edge.item;
943 d->baselineAnchorLine = edge.anchorLine;
944 d->remDepend(oldBaseline);
945 d->addDepend(d->baselineAnchorItem);
946 emit baselineChanged();
947 d->updateVerticalAnchors();
948 }
949
resetBaseline()950 void QQuickAnchors::resetBaseline()
951 {
952 Q_D(QQuickAnchors);
953 d->usedAnchors &= ~BaselineAnchor;
954 d->remDepend(d->baselineAnchorItem);
955 d->baselineAnchorItem = nullptr;
956 d->baselineAnchorLine = QQuickAnchors::InvalidAnchor;
957 emit baselineChanged();
958 d->updateVerticalAnchors();
959 }
960
left() const961 QQuickAnchorLine QQuickAnchors::left() const
962 {
963 Q_D(const QQuickAnchors);
964 return QQuickAnchorLine(d->leftAnchorItem, d->leftAnchorLine);
965 }
966
setLeft(const QQuickAnchorLine & edge)967 void QQuickAnchors::setLeft(const QQuickAnchorLine &edge)
968 {
969 Q_D(QQuickAnchors);
970 if (!d->checkHAnchorValid(edge) ||
971 (d->leftAnchorItem == edge.item && d->leftAnchorLine == edge.anchorLine))
972 return;
973
974 d->usedAnchors |= LeftAnchor;
975
976 if (!d->checkHValid()) {
977 d->usedAnchors &= ~LeftAnchor;
978 return;
979 }
980
981 QQuickItem *oldLeft = d->leftAnchorItem;
982 d->leftAnchorItem = edge.item;
983 d->leftAnchorLine = edge.anchorLine;
984 d->remDepend(oldLeft);
985 d->addDepend(d->leftAnchorItem);
986 emit leftChanged();
987 d->updateHorizontalAnchors();
988 }
989
resetLeft()990 void QQuickAnchors::resetLeft()
991 {
992 Q_D(QQuickAnchors);
993 d->usedAnchors &= ~LeftAnchor;
994 d->remDepend(d->leftAnchorItem);
995 d->leftAnchorItem = nullptr;
996 d->leftAnchorLine = QQuickAnchors::InvalidAnchor;
997 emit leftChanged();
998 d->updateHorizontalAnchors();
999 }
1000
right() const1001 QQuickAnchorLine QQuickAnchors::right() const
1002 {
1003 Q_D(const QQuickAnchors);
1004 return QQuickAnchorLine(d->rightAnchorItem, d->rightAnchorLine);
1005 }
1006
setRight(const QQuickAnchorLine & edge)1007 void QQuickAnchors::setRight(const QQuickAnchorLine &edge)
1008 {
1009 Q_D(QQuickAnchors);
1010 if (!d->checkHAnchorValid(edge) ||
1011 (d->rightAnchorItem == edge.item && d->rightAnchorLine == edge.anchorLine))
1012 return;
1013
1014 d->usedAnchors |= RightAnchor;
1015
1016 if (!d->checkHValid()) {
1017 d->usedAnchors &= ~RightAnchor;
1018 return;
1019 }
1020
1021 QQuickItem *oldRight = d->rightAnchorItem;
1022 d->rightAnchorItem = edge.item;
1023 d->rightAnchorLine = edge.anchorLine;
1024 d->remDepend(oldRight);
1025 d->addDepend(d->rightAnchorItem);
1026 emit rightChanged();
1027 d->updateHorizontalAnchors();
1028 }
1029
resetRight()1030 void QQuickAnchors::resetRight()
1031 {
1032 Q_D(QQuickAnchors);
1033 d->usedAnchors &= ~RightAnchor;
1034 d->remDepend(d->rightAnchorItem);
1035 d->rightAnchorItem = nullptr;
1036 d->rightAnchorLine = QQuickAnchors::InvalidAnchor;
1037 emit rightChanged();
1038 d->updateHorizontalAnchors();
1039 }
1040
horizontalCenter() const1041 QQuickAnchorLine QQuickAnchors::horizontalCenter() const
1042 {
1043 Q_D(const QQuickAnchors);
1044 return QQuickAnchorLine(d->hCenterAnchorItem, d->hCenterAnchorLine);
1045 }
1046
setHorizontalCenter(const QQuickAnchorLine & edge)1047 void QQuickAnchors::setHorizontalCenter(const QQuickAnchorLine &edge)
1048 {
1049 Q_D(QQuickAnchors);
1050 if (!d->checkHAnchorValid(edge) ||
1051 (d->hCenterAnchorItem == edge.item && d->hCenterAnchorLine == edge.anchorLine))
1052 return;
1053
1054 d->usedAnchors |= HCenterAnchor;
1055
1056 if (!d->checkHValid()) {
1057 d->usedAnchors &= ~HCenterAnchor;
1058 return;
1059 }
1060
1061 QQuickItem *oldHCenter = d->hCenterAnchorItem;
1062 d->hCenterAnchorItem = edge.item;
1063 d->hCenterAnchorLine = edge.anchorLine;
1064 d->remDepend(oldHCenter);
1065 d->addDepend(d->hCenterAnchorItem);
1066 emit horizontalCenterChanged();
1067 d->updateHorizontalAnchors();
1068 }
1069
resetHorizontalCenter()1070 void QQuickAnchors::resetHorizontalCenter()
1071 {
1072 Q_D(QQuickAnchors);
1073 d->usedAnchors &= ~HCenterAnchor;
1074 d->remDepend(d->hCenterAnchorItem);
1075 d->hCenterAnchorItem = nullptr;
1076 d->hCenterAnchorLine = QQuickAnchors::InvalidAnchor;
1077 emit horizontalCenterChanged();
1078 d->updateHorizontalAnchors();
1079 }
1080
leftMargin() const1081 qreal QQuickAnchors::leftMargin() const
1082 {
1083 Q_D(const QQuickAnchors);
1084 return d->leftMargin;
1085 }
1086
setLeftMargin(qreal offset)1087 void QQuickAnchors::setLeftMargin(qreal offset)
1088 {
1089 Q_D(QQuickAnchors);
1090 d->leftMarginExplicit = true;
1091 if (d->leftMargin == offset)
1092 return;
1093 d->leftMargin = offset;
1094 if (d->fill)
1095 d->fillChanged();
1096 else
1097 d->updateHorizontalAnchors();
1098 emit leftMarginChanged();
1099 }
1100
resetLeftMargin()1101 void QQuickAnchors::resetLeftMargin()
1102 {
1103 Q_D(QQuickAnchors);
1104 d->leftMarginExplicit = false;
1105 if (d->leftMargin == d->margins)
1106 return;
1107 d->leftMargin = d->margins;
1108 if (d->fill)
1109 d->fillChanged();
1110 else
1111 d->updateHorizontalAnchors();
1112 emit leftMarginChanged();
1113 }
1114
rightMargin() const1115 qreal QQuickAnchors::rightMargin() const
1116 {
1117 Q_D(const QQuickAnchors);
1118 return d->rightMargin;
1119 }
1120
setRightMargin(qreal offset)1121 void QQuickAnchors::setRightMargin(qreal offset)
1122 {
1123 Q_D(QQuickAnchors);
1124 d->rightMarginExplicit = true;
1125 if (d->rightMargin == offset)
1126 return;
1127 d->rightMargin = offset;
1128 if (d->fill)
1129 d->fillChanged();
1130 else
1131 d->updateHorizontalAnchors();
1132 emit rightMarginChanged();
1133 }
1134
resetRightMargin()1135 void QQuickAnchors::resetRightMargin()
1136 {
1137 Q_D(QQuickAnchors);
1138 d->rightMarginExplicit = false;
1139 if (d->rightMargin == d->margins)
1140 return;
1141 d->rightMargin = d->margins;
1142 if (d->fill)
1143 d->fillChanged();
1144 else
1145 d->updateHorizontalAnchors();
1146 emit rightMarginChanged();
1147 }
1148
margins() const1149 qreal QQuickAnchors::margins() const
1150 {
1151 Q_D(const QQuickAnchors);
1152 return d->margins;
1153 }
1154
setMargins(qreal offset)1155 void QQuickAnchors::setMargins(qreal offset)
1156 {
1157 Q_D(QQuickAnchors);
1158 if (d->margins == offset)
1159 return;
1160 d->margins = offset;
1161
1162 bool updateHorizontal = false;
1163 bool updateVertical = false;
1164
1165 if (!d->rightMarginExplicit && d->rightMargin != offset) {
1166 d->rightMargin = offset;
1167 updateHorizontal = true;
1168 emit rightMarginChanged();
1169 }
1170 if (!d->leftMarginExplicit && d->leftMargin != offset) {
1171 d->leftMargin = offset;
1172 updateHorizontal = true;
1173 emit leftMarginChanged();
1174 }
1175 if (!d->topMarginExplicit && d->topMargin != offset) {
1176 d->topMargin = offset;
1177 updateVertical = true;
1178 emit topMarginChanged();
1179 }
1180 if (!d->bottomMarginExplicit && d->bottomMargin != offset) {
1181 d->bottomMargin = offset;
1182 updateVertical = true;
1183 emit bottomMarginChanged();
1184 }
1185
1186 if (d->fill) {
1187 if (updateHorizontal || updateVertical)
1188 d->fillChanged();
1189 } else {
1190 if (updateHorizontal)
1191 d->updateHorizontalAnchors();
1192 if (updateVertical)
1193 d->updateVerticalAnchors();
1194 }
1195
1196 emit marginsChanged();
1197 }
1198
horizontalCenterOffset() const1199 qreal QQuickAnchors::horizontalCenterOffset() const
1200 {
1201 Q_D(const QQuickAnchors);
1202 return d->hCenterOffset;
1203 }
1204
setHorizontalCenterOffset(qreal offset)1205 void QQuickAnchors::setHorizontalCenterOffset(qreal offset)
1206 {
1207 Q_D(QQuickAnchors);
1208 if (d->hCenterOffset == offset)
1209 return;
1210 d->hCenterOffset = offset;
1211 if (d->centerIn)
1212 d->centerInChanged();
1213 else
1214 d->updateHorizontalAnchors();
1215 emit horizontalCenterOffsetChanged();
1216 }
1217
topMargin() const1218 qreal QQuickAnchors::topMargin() const
1219 {
1220 Q_D(const QQuickAnchors);
1221 return d->topMargin;
1222 }
1223
setTopMargin(qreal offset)1224 void QQuickAnchors::setTopMargin(qreal offset)
1225 {
1226 Q_D(QQuickAnchors);
1227 d->topMarginExplicit = true;
1228 if (d->topMargin == offset)
1229 return;
1230 d->topMargin = offset;
1231 if (d->fill)
1232 d->fillChanged();
1233 else
1234 d->updateVerticalAnchors();
1235 emit topMarginChanged();
1236 }
1237
resetTopMargin()1238 void QQuickAnchors::resetTopMargin()
1239 {
1240 Q_D(QQuickAnchors);
1241 d->topMarginExplicit = false;
1242 if (d->topMargin == d->margins)
1243 return;
1244 d->topMargin = d->margins;
1245 if (d->fill)
1246 d->fillChanged();
1247 else
1248 d->updateVerticalAnchors();
1249 emit topMarginChanged();
1250 }
1251
bottomMargin() const1252 qreal QQuickAnchors::bottomMargin() const
1253 {
1254 Q_D(const QQuickAnchors);
1255 return d->bottomMargin;
1256 }
1257
setBottomMargin(qreal offset)1258 void QQuickAnchors::setBottomMargin(qreal offset)
1259 {
1260 Q_D(QQuickAnchors);
1261 d->bottomMarginExplicit = true;
1262 if (d->bottomMargin == offset)
1263 return;
1264 d->bottomMargin = offset;
1265 if (d->fill)
1266 d->fillChanged();
1267 else
1268 d->updateVerticalAnchors();
1269 emit bottomMarginChanged();
1270 }
1271
resetBottomMargin()1272 void QQuickAnchors::resetBottomMargin()
1273 {
1274 Q_D(QQuickAnchors);
1275 d->bottomMarginExplicit = false;
1276 if (d->bottomMargin == d->margins)
1277 return;
1278 d->bottomMargin = d->margins;
1279 if (d->fill)
1280 d->fillChanged();
1281 else
1282 d->updateVerticalAnchors();
1283 emit bottomMarginChanged();
1284 }
1285
verticalCenterOffset() const1286 qreal QQuickAnchors::verticalCenterOffset() const
1287 {
1288 Q_D(const QQuickAnchors);
1289 return d->vCenterOffset;
1290 }
1291
setVerticalCenterOffset(qreal offset)1292 void QQuickAnchors::setVerticalCenterOffset(qreal offset)
1293 {
1294 Q_D(QQuickAnchors);
1295 if (d->vCenterOffset == offset)
1296 return;
1297 d->vCenterOffset = offset;
1298 if (d->centerIn)
1299 d->centerInChanged();
1300 else
1301 d->updateVerticalAnchors();
1302 emit verticalCenterOffsetChanged();
1303 }
1304
baselineOffset() const1305 qreal QQuickAnchors::baselineOffset() const
1306 {
1307 Q_D(const QQuickAnchors);
1308 return d->baselineOffset;
1309 }
1310
setBaselineOffset(qreal offset)1311 void QQuickAnchors::setBaselineOffset(qreal offset)
1312 {
1313 Q_D(QQuickAnchors);
1314 if (d->baselineOffset == offset)
1315 return;
1316 d->baselineOffset = offset;
1317 d->updateVerticalAnchors();
1318 emit baselineOffsetChanged();
1319 }
1320
usedAnchors() const1321 QQuickAnchors::Anchors QQuickAnchors::usedAnchors() const
1322 {
1323 Q_D(const QQuickAnchors);
1324 return static_cast<QQuickAnchors::Anchors>(d->usedAnchors);
1325 }
1326
activeDirections() const1327 Qt::Orientations QQuickAnchors::activeDirections() const
1328 {
1329 Q_D(const QQuickAnchors);
1330 if (d->fill || d->centerIn)
1331 return Qt::Horizontal | Qt::Vertical;
1332 Qt::Orientations o;
1333 if (d->usedAnchors & QQuickAnchors::Horizontal_Mask)
1334 o |= Qt::Horizontal;
1335 if (d->usedAnchors & QQuickAnchors::Vertical_Mask)
1336 o |= Qt::Vertical;
1337 return o;
1338 }
1339
checkHValid() const1340 bool QQuickAnchorsPrivate::checkHValid() const
1341 {
1342 if (usedAnchors & QQuickAnchors::LeftAnchor &&
1343 usedAnchors & QQuickAnchors::RightAnchor &&
1344 usedAnchors & QQuickAnchors::HCenterAnchor) {
1345 qmlWarning(item) << QQuickAnchors::tr("Cannot specify left, right, and horizontalCenter anchors at the same time.");
1346 return false;
1347 }
1348
1349 return true;
1350 }
1351
checkHAnchorValid(QQuickAnchorLine anchor) const1352 bool QQuickAnchorsPrivate::checkHAnchorValid(QQuickAnchorLine anchor) const
1353 {
1354 if (!anchor.item) {
1355 qmlWarning(item) << QQuickAnchors::tr("Cannot anchor to a null item.");
1356 return false;
1357 } else if (anchor.anchorLine & QQuickAnchors::Vertical_Mask) {
1358 qmlWarning(item) << QQuickAnchors::tr("Cannot anchor a horizontal edge to a vertical edge.");
1359 return false;
1360 } else if (anchor.item != readParentItem(item)
1361 && readParentItem(anchor.item) != readParentItem(item)) {
1362 qmlWarning(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
1363 return false;
1364 } else if (anchor.item == item) {
1365 qmlWarning(item) << QQuickAnchors::tr("Cannot anchor item to self.");
1366 return false;
1367 }
1368
1369 return true;
1370 }
1371
checkVValid() const1372 bool QQuickAnchorsPrivate::checkVValid() const
1373 {
1374 if (usedAnchors & QQuickAnchors::TopAnchor &&
1375 usedAnchors & QQuickAnchors::BottomAnchor &&
1376 usedAnchors & QQuickAnchors::VCenterAnchor) {
1377 qmlWarning(item) << QQuickAnchors::tr("Cannot specify top, bottom, and verticalCenter anchors at the same time.");
1378 return false;
1379 } else if (usedAnchors & QQuickAnchors::BaselineAnchor &&
1380 (usedAnchors & QQuickAnchors::TopAnchor ||
1381 usedAnchors & QQuickAnchors::BottomAnchor ||
1382 usedAnchors & QQuickAnchors::VCenterAnchor)) {
1383 qmlWarning(item) << QQuickAnchors::tr("Baseline anchor cannot be used in conjunction with top, bottom, or verticalCenter anchors.");
1384 return false;
1385 }
1386
1387 return true;
1388 }
1389
checkVAnchorValid(QQuickAnchorLine anchor) const1390 bool QQuickAnchorsPrivate::checkVAnchorValid(QQuickAnchorLine anchor) const
1391 {
1392 if (!anchor.item) {
1393 qmlWarning(item) << QQuickAnchors::tr("Cannot anchor to a null item.");
1394 return false;
1395 } else if (anchor.anchorLine & QQuickAnchors::Horizontal_Mask) {
1396 qmlWarning(item) << QQuickAnchors::tr("Cannot anchor a vertical edge to a horizontal edge.");
1397 return false;
1398 } else if (anchor.item != readParentItem(item)
1399 && readParentItem(anchor.item) != readParentItem(item)) {
1400 qmlWarning(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
1401 return false;
1402 } else if (anchor.item == item){
1403 qmlWarning(item) << QQuickAnchors::tr("Cannot anchor item to self.");
1404 return false;
1405 }
1406
1407 return true;
1408 }
1409
1410 QT_END_NAMESPACE
1411
1412 #include <moc_qquickanchors_p.cpp>
1413
1414