51 QT_BEGIN_NAMESPACE |
51 QT_BEGIN_NAMESPACE |
52 |
52 |
53 //TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)? |
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) |
54 //TODO: support non-parent, non-sibling (need to find lowest common ancestor) |
55 |
55 |
|
56 static 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 |
|
68 static 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 |
56 //### const item? |
80 //### const item? |
57 //local position |
81 //local position |
58 static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine) |
82 static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine) |
59 { |
83 { |
60 qreal ret = 0.0; |
84 qreal ret = 0.0; |
71 break; |
95 break; |
72 case QDeclarativeAnchorLine::Bottom: |
96 case QDeclarativeAnchorLine::Bottom: |
73 ret = item->y() + d->height(); |
97 ret = item->y() + d->height(); |
74 break; |
98 break; |
75 case QDeclarativeAnchorLine::HCenter: |
99 case QDeclarativeAnchorLine::HCenter: |
76 ret = item->x() + d->width()/2; |
100 ret = item->x() + hcenter(item); |
77 break; |
101 break; |
78 case QDeclarativeAnchorLine::VCenter: |
102 case QDeclarativeAnchorLine::VCenter: |
79 ret = item->y() + d->height()/2; |
103 ret = item->y() + vcenter(item); |
80 break; |
104 break; |
81 case QDeclarativeAnchorLine::Baseline: |
105 case QDeclarativeAnchorLine::Baseline: |
82 if (d->isDeclarativeItem) |
106 if (d->isDeclarativeItem) |
83 ret = item->y() + static_cast<QDeclarativeItem*>(item)->baselineOffset(); |
107 ret = item->y() + static_cast<QDeclarativeItem*>(item)->baselineOffset(); |
84 break; |
108 break; |
90 } |
114 } |
91 |
115 |
92 //position when origin is 0,0 |
116 //position when origin is 0,0 |
93 static qreal adjustedPosition(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine) |
117 static qreal adjustedPosition(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine) |
94 { |
118 { |
95 int ret = 0; |
119 qreal ret = 0.0; |
96 QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item); |
120 QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item); |
97 switch(anchorLine) { |
121 switch(anchorLine) { |
98 case QDeclarativeAnchorLine::Left: |
122 case QDeclarativeAnchorLine::Left: |
99 ret = 0; |
123 ret = 0.0; |
100 break; |
124 break; |
101 case QDeclarativeAnchorLine::Right: |
125 case QDeclarativeAnchorLine::Right: |
102 ret = d->width(); |
126 ret = d->width(); |
103 break; |
127 break; |
104 case QDeclarativeAnchorLine::Top: |
128 case QDeclarativeAnchorLine::Top: |
105 ret = 0; |
129 ret = 0.0; |
106 break; |
130 break; |
107 case QDeclarativeAnchorLine::Bottom: |
131 case QDeclarativeAnchorLine::Bottom: |
108 ret = d->height(); |
132 ret = d->height(); |
109 break; |
133 break; |
110 case QDeclarativeAnchorLine::HCenter: |
134 case QDeclarativeAnchorLine::HCenter: |
111 ret = d->width()/2; |
135 ret = hcenter(item); |
112 break; |
136 break; |
113 case QDeclarativeAnchorLine::VCenter: |
137 case QDeclarativeAnchorLine::VCenter: |
114 ret = d->height()/2; |
138 ret = vcenter(item); |
115 break; |
139 break; |
116 case QDeclarativeAnchorLine::Baseline: |
140 case QDeclarativeAnchorLine::Baseline: |
117 if (d->isDeclarativeItem) |
141 if (d->isDeclarativeItem) |
118 ret = static_cast<QDeclarativeItem*>(item)->baselineOffset(); |
142 ret = static_cast<QDeclarativeItem*>(item)->baselineOffset(); |
119 break; |
143 break; |
187 if (!centerIn || fill || !isItemComplete()) |
211 if (!centerIn || fill || !isItemComplete()) |
188 return; |
212 return; |
189 |
213 |
190 if (updatingCenterIn < 2) { |
214 if (updatingCenterIn < 2) { |
191 ++updatingCenterIn; |
215 ++updatingCenterIn; |
192 QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item); |
|
193 if (centerIn == item->parentItem()) { |
216 if (centerIn == item->parentItem()) { |
194 QGraphicsItemPrivate *parentPrivate = QGraphicsItemPrivate::get(item->parentItem()); |
217 QPointF p(hcenter(item->parentItem()) - hcenter(item) + hCenterOffset, |
195 QPointF p((parentPrivate->width() - itemPrivate->width()) / 2. + hCenterOffset, |
218 vcenter(item->parentItem()) - vcenter(item) + vCenterOffset); |
196 (parentPrivate->height() - itemPrivate->height()) / 2. + vCenterOffset); |
|
197 setItemPos(p); |
219 setItemPos(p); |
198 |
220 |
199 } else if (centerIn->parentItem() == item->parentItem()) { |
221 } else if (centerIn->parentItem() == item->parentItem()) { |
200 QGraphicsItemPrivate *centerPrivate = QGraphicsItemPrivate::get(centerIn); |
222 QPointF p(centerIn->x() + hcenter(centerIn) - hcenter(item) + hCenterOffset, |
201 QPointF p(centerIn->x() + (centerPrivate->width() - itemPrivate->width()) / 2. + hCenterOffset, |
223 centerIn->y() + vcenter(centerIn) - vcenter(item) + vCenterOffset); |
202 centerIn->y() + (centerPrivate->height() - itemPrivate->height()) / 2. + vCenterOffset); |
|
203 setItemPos(p); |
224 setItemPos(p); |
204 } |
225 } |
205 |
226 |
206 --updatingCenterIn; |
227 --updatingCenterIn; |
207 } else { |
228 } else { |
457 setCenterIn(0); |
478 setCenterIn(0); |
458 } |
479 } |
459 |
480 |
460 bool QDeclarativeAnchorsPrivate::calcStretch(const QDeclarativeAnchorLine &edge1, |
481 bool QDeclarativeAnchorsPrivate::calcStretch(const QDeclarativeAnchorLine &edge1, |
461 const QDeclarativeAnchorLine &edge2, |
482 const QDeclarativeAnchorLine &edge2, |
462 int offset1, |
483 qreal offset1, |
463 int offset2, |
484 qreal offset2, |
464 QDeclarativeAnchorLine::AnchorLine line, |
485 QDeclarativeAnchorLine::AnchorLine line, |
465 int &stretch) |
486 qreal &stretch) |
466 { |
487 { |
467 bool edge1IsParent = (edge1.item == item->parentItem()); |
488 bool edge1IsParent = (edge1.item == item->parentItem()); |
468 bool edge2IsParent = (edge2.item == item->parentItem()); |
489 bool edge2IsParent = (edge2.item == item->parentItem()); |
469 bool edge1IsSibling = (edge1.item->parentItem() == item->parentItem()); |
490 bool edge1IsSibling = (edge1.item->parentItem() == item->parentItem()); |
470 bool edge2IsSibling = (edge2.item->parentItem() == item->parentItem()); |
491 bool edge2IsSibling = (edge2.item->parentItem() == item->parentItem()); |
471 |
492 |
472 bool invalid = false; |
493 bool invalid = false; |
473 if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) { |
494 if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) { |
474 stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2) |
495 stretch = (position(edge2.item, edge2.anchorLine) + offset2) |
475 - ((int)position(edge1.item, edge1.anchorLine) + offset1); |
496 - (position(edge1.item, edge1.anchorLine) + offset1); |
476 } else if (edge2IsParent && edge1IsSibling) { |
497 } else if (edge2IsParent && edge1IsSibling) { |
477 stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2) |
498 stretch = (position(edge2.item, edge2.anchorLine) + offset2) |
478 - ((int)position(item->parentObject(), line) |
499 - (position(item->parentObject(), line) |
479 + (int)position(edge1.item, edge1.anchorLine) + offset1); |
500 + position(edge1.item, edge1.anchorLine) + offset1); |
480 } else if (edge2IsSibling && edge1IsParent) { |
501 } else if (edge2IsSibling && edge1IsParent) { |
481 stretch = ((int)position(item->parentObject(), line) + (int)position(edge2.item, edge2.anchorLine) + offset2) |
502 stretch = (position(item->parentObject(), line) + position(edge2.item, edge2.anchorLine) + offset2) |
482 - ((int)position(edge1.item, edge1.anchorLine) + offset1); |
503 - (position(edge1.item, edge1.anchorLine) + offset1); |
483 } else |
504 } else |
484 invalid = true; |
505 invalid = true; |
485 |
506 |
486 return invalid; |
507 return invalid; |
487 } |
508 } |
495 ++updatingVerticalAnchor; |
516 ++updatingVerticalAnchor; |
496 QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item); |
517 QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item); |
497 if (usedAnchors & QDeclarativeAnchors::TopAnchor) { |
518 if (usedAnchors & QDeclarativeAnchors::TopAnchor) { |
498 //Handle stretching |
519 //Handle stretching |
499 bool invalid = true; |
520 bool invalid = true; |
500 int height = 0; |
521 qreal height = 0.0; |
501 if (usedAnchors & QDeclarativeAnchors::BottomAnchor) { |
522 if (usedAnchors & QDeclarativeAnchors::BottomAnchor) { |
502 invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QDeclarativeAnchorLine::Top, height); |
523 invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QDeclarativeAnchorLine::Top, height); |
503 } else if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) { |
524 } else if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) { |
504 invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QDeclarativeAnchorLine::Top, height); |
525 invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QDeclarativeAnchorLine::Top, height); |
505 height *= 2; |
526 height *= 2; |
514 setItemY(position(top.item, top.anchorLine) + topMargin); |
535 setItemY(position(top.item, top.anchorLine) + topMargin); |
515 } |
536 } |
516 } else if (usedAnchors & QDeclarativeAnchors::BottomAnchor) { |
537 } else if (usedAnchors & QDeclarativeAnchors::BottomAnchor) { |
517 //Handle stretching (top + bottom case is handled above) |
538 //Handle stretching (top + bottom case is handled above) |
518 if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) { |
539 if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) { |
519 int height = 0; |
540 qreal height = 0.0; |
520 bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin, |
541 bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin, |
521 QDeclarativeAnchorLine::Top, height); |
542 QDeclarativeAnchorLine::Top, height); |
522 if (!invalid) |
543 if (!invalid) |
523 setItemHeight(height*2); |
544 setItemHeight(height*2); |
524 } |
545 } |
533 //(stetching handled above) |
554 //(stetching handled above) |
534 |
555 |
535 //Handle vCenter |
556 //Handle vCenter |
536 if (vCenter.item == item->parentItem()) { |
557 if (vCenter.item == item->parentItem()) { |
537 setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine) |
558 setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine) |
538 - itemPrivate->height()/2 + vCenterOffset); |
559 - vcenter(item) + vCenterOffset); |
539 } else if (vCenter.item->parentItem() == item->parentItem()) { |
560 } else if (vCenter.item->parentItem() == item->parentItem()) { |
540 setItemY(position(vCenter.item, vCenter.anchorLine) - itemPrivate->height()/2 + vCenterOffset); |
561 setItemY(position(vCenter.item, vCenter.anchorLine) - vcenter(item) + vCenterOffset); |
541 } |
562 } |
542 } else if (usedAnchors & QDeclarativeAnchors::BaselineAnchor) { |
563 } else if (usedAnchors & QDeclarativeAnchors::BaselineAnchor) { |
543 //Handle baseline |
564 //Handle baseline |
544 if (baseline.item == item->parentItem()) { |
565 if (baseline.item == item->parentItem()) { |
545 if (itemPrivate->isDeclarativeItem) |
566 if (itemPrivate->isDeclarativeItem) |
567 ++updatingHorizontalAnchor; |
588 ++updatingHorizontalAnchor; |
568 QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item); |
589 QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item); |
569 if (usedAnchors & QDeclarativeAnchors::LeftAnchor) { |
590 if (usedAnchors & QDeclarativeAnchors::LeftAnchor) { |
570 //Handle stretching |
591 //Handle stretching |
571 bool invalid = true; |
592 bool invalid = true; |
572 int width = 0; |
593 qreal width = 0.0; |
573 if (usedAnchors & QDeclarativeAnchors::RightAnchor) { |
594 if (usedAnchors & QDeclarativeAnchors::RightAnchor) { |
574 invalid = calcStretch(left, right, leftMargin, -rightMargin, QDeclarativeAnchorLine::Left, width); |
595 invalid = calcStretch(left, right, leftMargin, -rightMargin, QDeclarativeAnchorLine::Left, width); |
575 } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { |
596 } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { |
576 invalid = calcStretch(left, hCenter, leftMargin, hCenterOffset, QDeclarativeAnchorLine::Left, width); |
597 invalid = calcStretch(left, hCenter, leftMargin, hCenterOffset, QDeclarativeAnchorLine::Left, width); |
577 width *= 2; |
598 width *= 2; |
586 setItemX(position(left.item, left.anchorLine) + leftMargin); |
607 setItemX(position(left.item, left.anchorLine) + leftMargin); |
587 } |
608 } |
588 } else if (usedAnchors & QDeclarativeAnchors::RightAnchor) { |
609 } else if (usedAnchors & QDeclarativeAnchors::RightAnchor) { |
589 //Handle stretching (left + right case is handled in updateLeftAnchor) |
610 //Handle stretching (left + right case is handled in updateLeftAnchor) |
590 if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { |
611 if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { |
591 int width = 0; |
612 qreal width = 0.0; |
592 bool invalid = calcStretch(hCenter, right, hCenterOffset, -rightMargin, |
613 bool invalid = calcStretch(hCenter, right, hCenterOffset, -rightMargin, |
593 QDeclarativeAnchorLine::Left, width); |
614 QDeclarativeAnchorLine::Left, width); |
594 if (!invalid) |
615 if (!invalid) |
595 setItemWidth(width*2); |
616 setItemWidth(width*2); |
596 } |
617 } |
602 setItemX(position(right.item, right.anchorLine) - itemPrivate->width() - rightMargin); |
623 setItemX(position(right.item, right.anchorLine) - itemPrivate->width() - rightMargin); |
603 } |
624 } |
604 } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { |
625 } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { |
605 //Handle hCenter |
626 //Handle hCenter |
606 if (hCenter.item == item->parentItem()) { |
627 if (hCenter.item == item->parentItem()) { |
607 setItemX(adjustedPosition(hCenter.item, hCenter.anchorLine) - itemPrivate->width()/2 + hCenterOffset); |
628 setItemX(adjustedPosition(hCenter.item, hCenter.anchorLine) - hcenter(item) + hCenterOffset); |
608 } else if (hCenter.item->parentItem() == item->parentItem()) { |
629 } else if (hCenter.item->parentItem() == item->parentItem()) { |
609 setItemX(position(hCenter.item, hCenter.anchorLine) - itemPrivate->width()/2 + hCenterOffset); |
630 setItemX(position(hCenter.item, hCenter.anchorLine) - hcenter(item) + hCenterOffset); |
610 } |
631 } |
611 } |
632 } |
612 |
633 |
613 --updatingHorizontalAnchor; |
634 --updatingHorizontalAnchor; |
614 } else { |
635 } else { |