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