source: trunk/src/declarative/graphicsitems/qdeclarativeanchors.cpp@ 846

Last change on this file since 846 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 33.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtDeclarative module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "private/qdeclarativeanchors_p_p.h"
43
44#include "qdeclarativeitem.h"
45#include "private/qdeclarativeitem_p.h"
46
47#include <qdeclarativeinfo.h>
48
49#include <QDebug>
50
51QT_BEGIN_NAMESPACE
52
53//TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
54//TODO: support non-parent, non-sibling (need to find lowest common ancestor)
55
56static qreal hcenter(QGraphicsItem *i)
57{
58 QGraphicsItemPrivate *item = QGraphicsItemPrivate::get(i);
59
60 qreal width = item->width();
61 int iw = width;
62 if (iw % 2)
63 return (width + 1) / 2;
64 else
65 return width / 2;
66}
67
68static qreal vcenter(QGraphicsItem *i)
69{
70 QGraphicsItemPrivate *item = QGraphicsItemPrivate::get(i);
71
72 qreal height = item->height();
73 int ih = height;
74 if (ih % 2)
75 return (height + 1) / 2;
76 else
77 return height / 2;
78}
79
80//### const item?
81//local position
82static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
83{
84 qreal ret = 0.0;
85 QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item);
86 switch(anchorLine) {
87 case QDeclarativeAnchorLine::Left:
88 ret = item->x();
89 break;
90 case QDeclarativeAnchorLine::Right:
91 ret = item->x() + d->width();
92 break;
93 case QDeclarativeAnchorLine::Top:
94 ret = item->y();
95 break;
96 case QDeclarativeAnchorLine::Bottom:
97 ret = item->y() + d->height();
98 break;
99 case QDeclarativeAnchorLine::HCenter:
100 ret = item->x() + hcenter(item);
101 break;
102 case QDeclarativeAnchorLine::VCenter:
103 ret = item->y() + vcenter(item);
104 break;
105 case QDeclarativeAnchorLine::Baseline:
106 if (d->isDeclarativeItem)
107 ret = item->y() + static_cast<QDeclarativeItem*>(item)->baselineOffset();
108 break;
109 default:
110 break;
111 }
112
113 return ret;
114}
115
116//position when origin is 0,0
117static qreal adjustedPosition(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
118{
119 qreal ret = 0.0;
120 QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item);
121 switch(anchorLine) {
122 case QDeclarativeAnchorLine::Left:
123 ret = 0.0;
124 break;
125 case QDeclarativeAnchorLine::Right:
126 ret = d->width();
127 break;
128 case QDeclarativeAnchorLine::Top:
129 ret = 0.0;
130 break;
131 case QDeclarativeAnchorLine::Bottom:
132 ret = d->height();
133 break;
134 case QDeclarativeAnchorLine::HCenter:
135 ret = hcenter(item);
136 break;
137 case QDeclarativeAnchorLine::VCenter:
138 ret = vcenter(item);
139 break;
140 case QDeclarativeAnchorLine::Baseline:
141 if (d->isDeclarativeItem)
142 ret = static_cast<QDeclarativeItem*>(item)->baselineOffset();
143 break;
144 default:
145 break;
146 }
147
148 return ret;
149}
150
151QDeclarativeAnchors::QDeclarativeAnchors(QObject *parent)
152 : QObject(*new QDeclarativeAnchorsPrivate(0), parent)
153{
154 qFatal("QDeclarativeAnchors::QDeclarativeAnchors(QObject*) called");
155}
156
157QDeclarativeAnchors::QDeclarativeAnchors(QGraphicsObject *item, QObject *parent)
158 : QObject(*new QDeclarativeAnchorsPrivate(item), parent)
159{
160}
161
162QDeclarativeAnchors::~QDeclarativeAnchors()
163{
164 Q_D(QDeclarativeAnchors);
165 d->remDepend(d->fill);
166 d->remDepend(d->centerIn);
167 d->remDepend(d->left.item);
168 d->remDepend(d->right.item);
169 d->remDepend(d->top.item);
170 d->remDepend(d->bottom.item);
171 d->remDepend(d->vCenter.item);
172 d->remDepend(d->hCenter.item);
173 d->remDepend(d->baseline.item);
174}
175
176void QDeclarativeAnchorsPrivate::fillChanged()
177{
178 if (!fill || !isItemComplete())
179 return;
180
181 if (updatingFill < 2) {
182 ++updatingFill;
183
184 if (fill == item->parentItem()) { //child-parent
185 setItemPos(QPointF(leftMargin, topMargin));
186 } else if (fill->parentItem() == item->parentItem()) { //siblings
187 setItemPos(QPointF(fill->x()+leftMargin, fill->y()+topMargin));
188 }
189 QGraphicsItemPrivate *fillPrivate = QGraphicsItemPrivate::get(fill);
190 setItemSize(QSizeF(fillPrivate->width()-leftMargin-rightMargin, fillPrivate->height()-topMargin-bottomMargin));
191
192 --updatingFill;
193 } else {
194 // ### Make this certain :)
195 qmlInfo(item) << QDeclarativeAnchors::tr("Possible anchor loop detected on fill.");
196 }
197
198}
199
200void QDeclarativeAnchorsPrivate::centerInChanged()
201{
202 if (!centerIn || fill || !isItemComplete())
203 return;
204
205 if (updatingCenterIn < 2) {
206 ++updatingCenterIn;
207 if (centerIn == item->parentItem()) {
208 QPointF p(hcenter(item->parentItem()) - hcenter(item) + hCenterOffset,
209 vcenter(item->parentItem()) - vcenter(item) + vCenterOffset);
210 setItemPos(p);
211
212 } else if (centerIn->parentItem() == item->parentItem()) {
213 QPointF p(centerIn->x() + hcenter(centerIn) - hcenter(item) + hCenterOffset,
214 centerIn->y() + vcenter(centerIn) - vcenter(item) + vCenterOffset);
215 setItemPos(p);
216 }
217
218 --updatingCenterIn;
219 } else {
220 // ### Make this certain :)
221 qmlInfo(item) << QDeclarativeAnchors::tr("Possible anchor loop detected on centerIn.");
222 }
223}
224
225void QDeclarativeAnchorsPrivate::clearItem(QGraphicsObject *item)
226{
227 if (!item)
228 return;
229 if (fill == item)
230 fill = 0;
231 if (centerIn == item)
232 centerIn = 0;
233 if (left.item == item) {
234 left.item = 0;
235 usedAnchors &= ~QDeclarativeAnchors::LeftAnchor;
236 }
237 if (right.item == item) {
238 right.item = 0;
239 usedAnchors &= ~QDeclarativeAnchors::RightAnchor;
240 }
241 if (top.item == item) {
242 top.item = 0;
243 usedAnchors &= ~QDeclarativeAnchors::TopAnchor;
244 }
245 if (bottom.item == item) {
246 bottom.item = 0;
247 usedAnchors &= ~QDeclarativeAnchors::BottomAnchor;
248 }
249 if (vCenter.item == item) {
250 vCenter.item = 0;
251 usedAnchors &= ~QDeclarativeAnchors::VCenterAnchor;
252 }
253 if (hCenter.item == item) {
254 hCenter.item = 0;
255 usedAnchors &= ~QDeclarativeAnchors::HCenterAnchor;
256 }
257 if (baseline.item == item) {
258 baseline.item = 0;
259 usedAnchors &= ~QDeclarativeAnchors::BaselineAnchor;
260 }
261}
262
263void QDeclarativeAnchorsPrivate::addDepend(QGraphicsObject *item)
264{
265 if (!item)
266 return;
267 QGraphicsItemPrivate * itemPrivate = QGraphicsItemPrivate::get(item);
268 if (itemPrivate->isDeclarativeItem) {
269 QDeclarativeItemPrivate *p =
270 static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(item));
271 p->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
272 } else if(itemPrivate->isWidget) {
273 Q_Q(QDeclarativeAnchors);
274 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
275 QObject::connect(widget, SIGNAL(destroyed(QObject*)), q, SLOT(_q_widgetDestroyed(QObject*)));
276 QObject::connect(widget, SIGNAL(geometryChanged()), q, SLOT(_q_widgetGeometryChanged()));
277 }
278}
279
280void QDeclarativeAnchorsPrivate::remDepend(QGraphicsObject *item)
281{
282 if (!item)
283 return;
284 QGraphicsItemPrivate * itemPrivate = QGraphicsItemPrivate::get(item);
285 if (itemPrivate->isDeclarativeItem) {
286 QDeclarativeItemPrivate *p =
287 static_cast<QDeclarativeItemPrivate *>(itemPrivate);
288 p->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
289 } else if(itemPrivate->isWidget) {
290 Q_Q(QDeclarativeAnchors);
291 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
292 QObject::disconnect(widget, SIGNAL(destroyed(QObject*)), q, SLOT(_q_widgetDestroyed(QObject*)));
293 QObject::disconnect(widget, SIGNAL(geometryChanged()), q, SLOT(_q_widgetGeometryChanged()));
294 }
295}
296
297bool QDeclarativeAnchorsPrivate::isItemComplete() const
298{
299 return componentComplete;
300}
301
302void QDeclarativeAnchors::classBegin()
303{
304 Q_D(QDeclarativeAnchors);
305 d->componentComplete = false;
306}
307
308void QDeclarativeAnchors::componentComplete()
309{
310 Q_D(QDeclarativeAnchors);
311 d->componentComplete = true;
312}
313
314void QDeclarativeAnchorsPrivate::setItemHeight(qreal v)
315{
316 updatingMe = true;
317 QGraphicsItemPrivate::get(item)->setHeight(v);
318 updatingMe = false;
319}
320
321void QDeclarativeAnchorsPrivate::setItemWidth(qreal v)
322{
323 updatingMe = true;
324 QGraphicsItemPrivate::get(item)->setWidth(v);
325 updatingMe = false;
326}
327
328void QDeclarativeAnchorsPrivate::setItemX(qreal v)
329{
330 updatingMe = true;
331 item->setX(v);
332 updatingMe = false;
333}
334
335void QDeclarativeAnchorsPrivate::setItemY(qreal v)
336{
337 updatingMe = true;
338 item->setY(v);
339 updatingMe = false;
340}
341
342void QDeclarativeAnchorsPrivate::setItemPos(const QPointF &v)
343{
344 updatingMe = true;
345 item->setPos(v);
346 updatingMe = false;
347}
348
349void QDeclarativeAnchorsPrivate::setItemSize(const QSizeF &v)
350{
351 updatingMe = true;
352 if(QGraphicsItemPrivate::get(item)->isWidget)
353 static_cast<QGraphicsWidget *>(item)->resize(v);
354 else if (QGraphicsItemPrivate::get(item)->isDeclarativeItem)
355 static_cast<QDeclarativeItem *>(item)->setSize(v);
356 updatingMe = false;
357}
358
359void QDeclarativeAnchorsPrivate::updateMe()
360{
361 if (updatingMe) {
362 updatingMe = false;
363 return;
364 }
365
366 fillChanged();
367 centerInChanged();
368 updateHorizontalAnchors();
369 updateVerticalAnchors();
370}
371
372void QDeclarativeAnchorsPrivate::updateOnComplete()
373{
374 fillChanged();
375 centerInChanged();
376 updateHorizontalAnchors();
377 updateVerticalAnchors();
378}
379
380void QDeclarativeAnchorsPrivate::_q_widgetDestroyed(QObject *obj)
381{
382 clearItem(qobject_cast<QGraphicsObject*>(obj));
383}
384
385void QDeclarativeAnchorsPrivate::_q_widgetGeometryChanged()
386{
387 fillChanged();
388 centerInChanged();
389 updateHorizontalAnchors();
390 updateVerticalAnchors();
391}
392
393void QDeclarativeAnchorsPrivate::itemGeometryChanged(QDeclarativeItem *, const QRectF &newG, const QRectF &oldG)
394{
395 fillChanged();
396 centerInChanged();
397 if (newG.x() != oldG.x() || newG.width() != oldG.width())
398 updateHorizontalAnchors();
399 if (newG.y() != oldG.y() || newG.height() != oldG.height())
400 updateVerticalAnchors();
401}
402
403QGraphicsObject *QDeclarativeAnchors::fill() const
404{
405 Q_D(const QDeclarativeAnchors);
406 return d->fill;
407}
408
409void QDeclarativeAnchors::setFill(QGraphicsObject *f)
410{
411 Q_D(QDeclarativeAnchors);
412 if (d->fill == f)
413 return;
414
415 if (!f) {
416 d->remDepend(d->fill);
417 d->fill = f;
418 emit fillChanged();
419 return;
420 }
421 if (f != d->item->parentItem() && f->parentItem() != d->item->parentItem()){
422 qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
423 return;
424 }
425 d->remDepend(d->fill);
426 d->fill = f;
427 d->addDepend(d->fill);
428 emit fillChanged();
429 d->fillChanged();
430}
431
432void QDeclarativeAnchors::resetFill()
433{
434 setFill(0);
435}
436
437QGraphicsObject *QDeclarativeAnchors::centerIn() const
438{
439 Q_D(const QDeclarativeAnchors);
440 return d->centerIn;
441}
442
443void QDeclarativeAnchors::setCenterIn(QGraphicsObject* c)
444{
445 Q_D(QDeclarativeAnchors);
446 if (d->centerIn == c)
447 return;
448
449 if (!c) {
450 d->remDepend(d->centerIn);
451 d->centerIn = c;
452 emit centerInChanged();
453 return;
454 }
455 if (c != d->item->parentItem() && c->parentItem() != d->item->parentItem()){
456 qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
457 return;
458 }
459
460 d->remDepend(d->centerIn);
461 d->centerIn = c;
462 d->addDepend(d->centerIn);
463 emit centerInChanged();
464 d->centerInChanged();
465}
466
467void QDeclarativeAnchors::resetCenterIn()
468{
469 setCenterIn(0);
470}
471
472bool QDeclarativeAnchorsPrivate::calcStretch(const QDeclarativeAnchorLine &edge1,
473 const QDeclarativeAnchorLine &edge2,
474 qreal offset1,
475 qreal offset2,
476 QDeclarativeAnchorLine::AnchorLine line,
477 qreal &stretch)
478{
479 bool edge1IsParent = (edge1.item == item->parentItem());
480 bool edge2IsParent = (edge2.item == item->parentItem());
481 bool edge1IsSibling = (edge1.item->parentItem() == item->parentItem());
482 bool edge2IsSibling = (edge2.item->parentItem() == item->parentItem());
483
484 bool invalid = false;
485 if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
486 stretch = (position(edge2.item, edge2.anchorLine) + offset2)
487 - (position(edge1.item, edge1.anchorLine) + offset1);
488 } else if (edge2IsParent && edge1IsSibling) {
489 stretch = (position(edge2.item, edge2.anchorLine) + offset2)
490 - (position(item->parentObject(), line)
491 + position(edge1.item, edge1.anchorLine) + offset1);
492 } else if (edge2IsSibling && edge1IsParent) {
493 stretch = (position(item->parentObject(), line) + position(edge2.item, edge2.anchorLine) + offset2)
494 - (position(edge1.item, edge1.anchorLine) + offset1);
495 } else
496 invalid = true;
497
498 return invalid;
499}
500
501void QDeclarativeAnchorsPrivate::updateVerticalAnchors()
502{
503 if (fill || centerIn || !isItemComplete())
504 return;
505
506 if (updatingVerticalAnchor < 2) {
507 ++updatingVerticalAnchor;
508 QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item);
509 if (usedAnchors & QDeclarativeAnchors::TopAnchor) {
510 //Handle stretching
511 bool invalid = true;
512 qreal height = 0.0;
513 if (usedAnchors & QDeclarativeAnchors::BottomAnchor) {
514 invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QDeclarativeAnchorLine::Top, height);
515 } else if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) {
516 invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QDeclarativeAnchorLine::Top, height);
517 height *= 2;
518 }
519 if (!invalid)
520 setItemHeight(height);
521
522 //Handle top
523 if (top.item == item->parentItem()) {
524 setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin);
525 } else if (top.item->parentItem() == item->parentItem()) {
526 setItemY(position(top.item, top.anchorLine) + topMargin);
527 }
528 } else if (usedAnchors & QDeclarativeAnchors::BottomAnchor) {
529 //Handle stretching (top + bottom case is handled above)
530 if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) {
531 qreal height = 0.0;
532 bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin,
533 QDeclarativeAnchorLine::Top, height);
534 if (!invalid)
535 setItemHeight(height*2);
536 }
537
538 //Handle bottom
539 if (bottom.item == item->parentItem()) {
540 setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - itemPrivate->height() - bottomMargin);
541 } else if (bottom.item->parentItem() == item->parentItem()) {
542 setItemY(position(bottom.item, bottom.anchorLine) - itemPrivate->height() - bottomMargin);
543 }
544 } else if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) {
545 //(stetching handled above)
546
547 //Handle vCenter
548 if (vCenter.item == item->parentItem()) {
549 setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine)
550 - vcenter(item) + vCenterOffset);
551 } else if (vCenter.item->parentItem() == item->parentItem()) {
552 setItemY(position(vCenter.item, vCenter.anchorLine) - vcenter(item) + vCenterOffset);
553 }
554 } else if (usedAnchors & QDeclarativeAnchors::BaselineAnchor) {
555 //Handle baseline
556 if (baseline.item == item->parentItem()) {
557 if (itemPrivate->isDeclarativeItem)
558 setItemY(adjustedPosition(baseline.item, baseline.anchorLine)
559 - static_cast<QDeclarativeItem *>(item)->baselineOffset() + baselineOffset);
560 } else if (baseline.item->parentItem() == item->parentItem()) {
561 if (itemPrivate->isDeclarativeItem)
562 setItemY(position(baseline.item, baseline.anchorLine)
563 - static_cast<QDeclarativeItem *>(item)->baselineOffset() + baselineOffset);
564 }
565 }
566 --updatingVerticalAnchor;
567 } else {
568 // ### Make this certain :)
569 qmlInfo(item) << QDeclarativeAnchors::tr("Possible anchor loop detected on vertical anchor.");
570 }
571}
572
573void QDeclarativeAnchorsPrivate::updateHorizontalAnchors()
574{
575 if (fill || centerIn || !isItemComplete())
576 return;
577
578 if (updatingHorizontalAnchor < 2) {
579 ++updatingHorizontalAnchor;
580 QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item);
581 if (usedAnchors & QDeclarativeAnchors::LeftAnchor) {
582 //Handle stretching
583 bool invalid = true;
584 qreal width = 0.0;
585 if (usedAnchors & QDeclarativeAnchors::RightAnchor) {
586 invalid = calcStretch(left, right, leftMargin, -rightMargin, QDeclarativeAnchorLine::Left, width);
587 } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
588 invalid = calcStretch(left, hCenter, leftMargin, hCenterOffset, QDeclarativeAnchorLine::Left, width);
589 width *= 2;
590 }
591 if (!invalid)
592 setItemWidth(width);
593
594 //Handle left
595 if (left.item == item->parentItem()) {
596 setItemX(adjustedPosition(left.item, left.anchorLine) + leftMargin);
597 } else if (left.item->parentItem() == item->parentItem()) {
598 setItemX(position(left.item, left.anchorLine) + leftMargin);
599 }
600 } else if (usedAnchors & QDeclarativeAnchors::RightAnchor) {
601 //Handle stretching (left + right case is handled in updateLeftAnchor)
602 if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
603 qreal width = 0.0;
604 bool invalid = calcStretch(hCenter, right, hCenterOffset, -rightMargin,
605 QDeclarativeAnchorLine::Left, width);
606 if (!invalid)
607 setItemWidth(width*2);
608 }
609
610 //Handle right
611 if (right.item == item->parentItem()) {
612 setItemX(adjustedPosition(right.item, right.anchorLine) - itemPrivate->width() - rightMargin);
613 } else if (right.item->parentItem() == item->parentItem()) {
614 setItemX(position(right.item, right.anchorLine) - itemPrivate->width() - rightMargin);
615 }
616 } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
617 //Handle hCenter
618 if (hCenter.item == item->parentItem()) {
619 setItemX(adjustedPosition(hCenter.item, hCenter.anchorLine) - hcenter(item) + hCenterOffset);
620 } else if (hCenter.item->parentItem() == item->parentItem()) {
621 setItemX(position(hCenter.item, hCenter.anchorLine) - hcenter(item) + hCenterOffset);
622 }
623 }
624
625 --updatingHorizontalAnchor;
626 } else {
627 // ### Make this certain :)
628 qmlInfo(item) << QDeclarativeAnchors::tr("Possible anchor loop detected on horizontal anchor.");
629 }
630}
631
632QDeclarativeAnchorLine QDeclarativeAnchors::top() const
633{
634 Q_D(const QDeclarativeAnchors);
635 return d->top;
636}
637
638void QDeclarativeAnchors::setTop(const QDeclarativeAnchorLine &edge)
639{
640 Q_D(QDeclarativeAnchors);
641 if (!d->checkVAnchorValid(edge) || d->top == edge)
642 return;
643
644 d->usedAnchors |= TopAnchor;
645
646 if (!d->checkVValid()) {
647 d->usedAnchors &= ~TopAnchor;
648 return;
649 }
650
651 d->remDepend(d->top.item);
652 d->top = edge;
653 d->addDepend(d->top.item);
654 emit topChanged();
655 d->updateVerticalAnchors();
656}
657
658void QDeclarativeAnchors::resetTop()
659{
660 Q_D(QDeclarativeAnchors);
661 d->usedAnchors &= ~TopAnchor;
662 d->remDepend(d->top.item);
663 d->top = QDeclarativeAnchorLine();
664 emit topChanged();
665 d->updateVerticalAnchors();
666}
667
668QDeclarativeAnchorLine QDeclarativeAnchors::bottom() const
669{
670 Q_D(const QDeclarativeAnchors);
671 return d->bottom;
672}
673
674void QDeclarativeAnchors::setBottom(const QDeclarativeAnchorLine &edge)
675{
676 Q_D(QDeclarativeAnchors);
677 if (!d->checkVAnchorValid(edge) || d->bottom == edge)
678 return;
679
680 d->usedAnchors |= BottomAnchor;
681
682 if (!d->checkVValid()) {
683 d->usedAnchors &= ~BottomAnchor;
684 return;
685 }
686
687 d->remDepend(d->bottom.item);
688 d->bottom = edge;
689 d->addDepend(d->bottom.item);
690 emit bottomChanged();
691 d->updateVerticalAnchors();
692}
693
694void QDeclarativeAnchors::resetBottom()
695{
696 Q_D(QDeclarativeAnchors);
697 d->usedAnchors &= ~BottomAnchor;
698 d->remDepend(d->bottom.item);
699 d->bottom = QDeclarativeAnchorLine();
700 emit bottomChanged();
701 d->updateVerticalAnchors();
702}
703
704QDeclarativeAnchorLine QDeclarativeAnchors::verticalCenter() const
705{
706 Q_D(const QDeclarativeAnchors);
707 return d->vCenter;
708}
709
710void QDeclarativeAnchors::setVerticalCenter(const QDeclarativeAnchorLine &edge)
711{
712 Q_D(QDeclarativeAnchors);
713 if (!d->checkVAnchorValid(edge) || d->vCenter == edge)
714 return;
715
716 d->usedAnchors |= VCenterAnchor;
717
718 if (!d->checkVValid()) {
719 d->usedAnchors &= ~VCenterAnchor;
720 return;
721 }
722
723 d->remDepend(d->vCenter.item);
724 d->vCenter = edge;
725 d->addDepend(d->vCenter.item);
726 emit verticalCenterChanged();
727 d->updateVerticalAnchors();
728}
729
730void QDeclarativeAnchors::resetVerticalCenter()
731{
732 Q_D(QDeclarativeAnchors);
733 d->usedAnchors &= ~VCenterAnchor;
734 d->remDepend(d->vCenter.item);
735 d->vCenter = QDeclarativeAnchorLine();
736 emit verticalCenterChanged();
737 d->updateVerticalAnchors();
738}
739
740QDeclarativeAnchorLine QDeclarativeAnchors::baseline() const
741{
742 Q_D(const QDeclarativeAnchors);
743 return d->baseline;
744}
745
746void QDeclarativeAnchors::setBaseline(const QDeclarativeAnchorLine &edge)
747{
748 Q_D(QDeclarativeAnchors);
749 if (!d->checkVAnchorValid(edge) || d->baseline == edge)
750 return;
751
752 d->usedAnchors |= BaselineAnchor;
753
754 if (!d->checkVValid()) {
755 d->usedAnchors &= ~BaselineAnchor;
756 return;
757 }
758
759 d->remDepend(d->baseline.item);
760 d->baseline = edge;
761 d->addDepend(d->baseline.item);
762 emit baselineChanged();
763 d->updateVerticalAnchors();
764}
765
766void QDeclarativeAnchors::resetBaseline()
767{
768 Q_D(QDeclarativeAnchors);
769 d->usedAnchors &= ~BaselineAnchor;
770 d->remDepend(d->baseline.item);
771 d->baseline = QDeclarativeAnchorLine();
772 emit baselineChanged();
773 d->updateVerticalAnchors();
774}
775
776QDeclarativeAnchorLine QDeclarativeAnchors::left() const
777{
778 Q_D(const QDeclarativeAnchors);
779 return d->left;
780}
781
782void QDeclarativeAnchors::setLeft(const QDeclarativeAnchorLine &edge)
783{
784 Q_D(QDeclarativeAnchors);
785 if (!d->checkHAnchorValid(edge) || d->left == edge)
786 return;
787
788 d->usedAnchors |= LeftAnchor;
789
790 if (!d->checkHValid()) {
791 d->usedAnchors &= ~LeftAnchor;
792 return;
793 }
794
795 d->remDepend(d->left.item);
796 d->left = edge;
797 d->addDepend(d->left.item);
798 emit leftChanged();
799 d->updateHorizontalAnchors();
800}
801
802void QDeclarativeAnchors::resetLeft()
803{
804 Q_D(QDeclarativeAnchors);
805 d->usedAnchors &= ~LeftAnchor;
806 d->remDepend(d->left.item);
807 d->left = QDeclarativeAnchorLine();
808 emit leftChanged();
809 d->updateHorizontalAnchors();
810}
811
812QDeclarativeAnchorLine QDeclarativeAnchors::right() const
813{
814 Q_D(const QDeclarativeAnchors);
815 return d->right;
816}
817
818void QDeclarativeAnchors::setRight(const QDeclarativeAnchorLine &edge)
819{
820 Q_D(QDeclarativeAnchors);
821 if (!d->checkHAnchorValid(edge) || d->right == edge)
822 return;
823
824 d->usedAnchors |= RightAnchor;
825
826 if (!d->checkHValid()) {
827 d->usedAnchors &= ~RightAnchor;
828 return;
829 }
830
831 d->remDepend(d->right.item);
832 d->right = edge;
833 d->addDepend(d->right.item);
834 emit rightChanged();
835 d->updateHorizontalAnchors();
836}
837
838void QDeclarativeAnchors::resetRight()
839{
840 Q_D(QDeclarativeAnchors);
841 d->usedAnchors &= ~RightAnchor;
842 d->remDepend(d->right.item);
843 d->right = QDeclarativeAnchorLine();
844 emit rightChanged();
845 d->updateHorizontalAnchors();
846}
847
848QDeclarativeAnchorLine QDeclarativeAnchors::horizontalCenter() const
849{
850 Q_D(const QDeclarativeAnchors);
851 return d->hCenter;
852}
853
854void QDeclarativeAnchors::setHorizontalCenter(const QDeclarativeAnchorLine &edge)
855{
856 Q_D(QDeclarativeAnchors);
857 if (!d->checkHAnchorValid(edge) || d->hCenter == edge)
858 return;
859
860 d->usedAnchors |= HCenterAnchor;
861
862 if (!d->checkHValid()) {
863 d->usedAnchors &= ~HCenterAnchor;
864 return;
865 }
866
867 d->remDepend(d->hCenter.item);
868 d->hCenter = edge;
869 d->addDepend(d->hCenter.item);
870 emit horizontalCenterChanged();
871 d->updateHorizontalAnchors();
872}
873
874void QDeclarativeAnchors::resetHorizontalCenter()
875{
876 Q_D(QDeclarativeAnchors);
877 d->usedAnchors &= ~HCenterAnchor;
878 d->remDepend(d->hCenter.item);
879 d->hCenter = QDeclarativeAnchorLine();
880 emit horizontalCenterChanged();
881 d->updateHorizontalAnchors();
882}
883
884qreal QDeclarativeAnchors::leftMargin() const
885{
886 Q_D(const QDeclarativeAnchors);
887 return d->leftMargin;
888}
889
890void QDeclarativeAnchors::setLeftMargin(qreal offset)
891{
892 Q_D(QDeclarativeAnchors);
893 if (d->leftMargin == offset)
894 return;
895 d->leftMargin = offset;
896 if(d->fill)
897 d->fillChanged();
898 else
899 d->updateHorizontalAnchors();
900 emit leftMarginChanged();
901}
902
903qreal QDeclarativeAnchors::rightMargin() const
904{
905 Q_D(const QDeclarativeAnchors);
906 return d->rightMargin;
907}
908
909void QDeclarativeAnchors::setRightMargin(qreal offset)
910{
911 Q_D(QDeclarativeAnchors);
912 if (d->rightMargin == offset)
913 return;
914 d->rightMargin = offset;
915 if(d->fill)
916 d->fillChanged();
917 else
918 d->updateHorizontalAnchors();
919 emit rightMarginChanged();
920}
921
922qreal QDeclarativeAnchors::margins() const
923{
924 Q_D(const QDeclarativeAnchors);
925 return d->margins;
926}
927
928void QDeclarativeAnchors::setMargins(qreal offset)
929{
930 Q_D(QDeclarativeAnchors);
931 if (d->margins == offset)
932 return;
933 //###Is it significantly faster to set them directly so we can call fillChanged only once?
934 if(!d->rightMargin || d->rightMargin == d->margins)
935 setRightMargin(offset);
936 if(!d->leftMargin || d->leftMargin == d->margins)
937 setLeftMargin(offset);
938 if(!d->topMargin || d->topMargin == d->margins)
939 setTopMargin(offset);
940 if(!d->bottomMargin || d->bottomMargin == d->margins)
941 setBottomMargin(offset);
942 d->margins = offset;
943 emit marginsChanged();
944
945}
946
947qreal QDeclarativeAnchors::horizontalCenterOffset() const
948{
949 Q_D(const QDeclarativeAnchors);
950 return d->hCenterOffset;
951}
952
953void QDeclarativeAnchors::setHorizontalCenterOffset(qreal offset)
954{
955 Q_D(QDeclarativeAnchors);
956 if (d->hCenterOffset == offset)
957 return;
958 d->hCenterOffset = offset;
959 if(d->centerIn)
960 d->centerInChanged();
961 else
962 d->updateHorizontalAnchors();
963 emit horizontalCenterOffsetChanged();
964}
965
966qreal QDeclarativeAnchors::topMargin() const
967{
968 Q_D(const QDeclarativeAnchors);
969 return d->topMargin;
970}
971
972void QDeclarativeAnchors::setTopMargin(qreal offset)
973{
974 Q_D(QDeclarativeAnchors);
975 if (d->topMargin == offset)
976 return;
977 d->topMargin = offset;
978 if(d->fill)
979 d->fillChanged();
980 else
981 d->updateVerticalAnchors();
982 emit topMarginChanged();
983}
984
985qreal QDeclarativeAnchors::bottomMargin() const
986{
987 Q_D(const QDeclarativeAnchors);
988 return d->bottomMargin;
989}
990
991void QDeclarativeAnchors::setBottomMargin(qreal offset)
992{
993 Q_D(QDeclarativeAnchors);
994 if (d->bottomMargin == offset)
995 return;
996 d->bottomMargin = offset;
997 if(d->fill)
998 d->fillChanged();
999 else
1000 d->updateVerticalAnchors();
1001 emit bottomMarginChanged();
1002}
1003
1004qreal QDeclarativeAnchors::verticalCenterOffset() const
1005{
1006 Q_D(const QDeclarativeAnchors);
1007 return d->vCenterOffset;
1008}
1009
1010void QDeclarativeAnchors::setVerticalCenterOffset(qreal offset)
1011{
1012 Q_D(QDeclarativeAnchors);
1013 if (d->vCenterOffset == offset)
1014 return;
1015 d->vCenterOffset = offset;
1016 if(d->centerIn)
1017 d->centerInChanged();
1018 else
1019 d->updateVerticalAnchors();
1020 emit verticalCenterOffsetChanged();
1021}
1022
1023qreal QDeclarativeAnchors::baselineOffset() const
1024{
1025 Q_D(const QDeclarativeAnchors);
1026 return d->baselineOffset;
1027}
1028
1029void QDeclarativeAnchors::setBaselineOffset(qreal offset)
1030{
1031 Q_D(QDeclarativeAnchors);
1032 if (d->baselineOffset == offset)
1033 return;
1034 d->baselineOffset = offset;
1035 d->updateVerticalAnchors();
1036 emit baselineOffsetChanged();
1037}
1038
1039QDeclarativeAnchors::Anchors QDeclarativeAnchors::usedAnchors() const
1040{
1041 Q_D(const QDeclarativeAnchors);
1042 return d->usedAnchors;
1043}
1044
1045bool QDeclarativeAnchorsPrivate::checkHValid() const
1046{
1047 if (usedAnchors & QDeclarativeAnchors::LeftAnchor &&
1048 usedAnchors & QDeclarativeAnchors::RightAnchor &&
1049 usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
1050 qmlInfo(item) << QDeclarativeAnchors::tr("Cannot specify left, right, and hcenter anchors.");
1051 return false;
1052 }
1053
1054 return true;
1055}
1056
1057bool QDeclarativeAnchorsPrivate::checkHAnchorValid(QDeclarativeAnchorLine anchor) const
1058{
1059 if (!anchor.item) {
1060 qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor to a null item.");
1061 return false;
1062 } else if (anchor.anchorLine & QDeclarativeAnchorLine::Vertical_Mask) {
1063 qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor a horizontal edge to a vertical edge.");
1064 return false;
1065 } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
1066 qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
1067 return false;
1068 } else if (anchor.item == item) {
1069 qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor item to self.");
1070 return false;
1071 }
1072
1073 return true;
1074}
1075
1076bool QDeclarativeAnchorsPrivate::checkVValid() const
1077{
1078 if (usedAnchors & QDeclarativeAnchors::TopAnchor &&
1079 usedAnchors & QDeclarativeAnchors::BottomAnchor &&
1080 usedAnchors & QDeclarativeAnchors::VCenterAnchor) {
1081 qmlInfo(item) << QDeclarativeAnchors::tr("Cannot specify top, bottom, and vcenter anchors.");
1082 return false;
1083 } else if (usedAnchors & QDeclarativeAnchors::BaselineAnchor &&
1084 (usedAnchors & QDeclarativeAnchors::TopAnchor ||
1085 usedAnchors & QDeclarativeAnchors::BottomAnchor ||
1086 usedAnchors & QDeclarativeAnchors::VCenterAnchor)) {
1087 qmlInfo(item) << QDeclarativeAnchors::tr("Baseline anchor cannot be used in conjunction with top, bottom, or vcenter anchors.");
1088 return false;
1089 }
1090
1091 return true;
1092}
1093
1094bool QDeclarativeAnchorsPrivate::checkVAnchorValid(QDeclarativeAnchorLine anchor) const
1095{
1096 if (!anchor.item) {
1097 qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor to a null item.");
1098 return false;
1099 } else if (anchor.anchorLine & QDeclarativeAnchorLine::Horizontal_Mask) {
1100 qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor a vertical edge to a horizontal edge.");
1101 return false;
1102 } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
1103 qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
1104 return false;
1105 } else if (anchor.item == item){
1106 qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor item to self.");
1107 return false;
1108 }
1109
1110 return true;
1111}
1112
1113QT_END_NAMESPACE
1114
1115#include <moc_qdeclarativeanchors_p.cpp>
1116
Note: See TracBrowser for help on using the repository browser.