summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/declarative/flickr/content/ImageDetails.qml1
-rw-r--r--src/declarative/fx/qfxanchors.cpp717
-rw-r--r--src/declarative/fx/qfxanchors.h12
-rw-r--r--src/declarative/fx/qfxanchors_p.h36
-rw-r--r--src/declarative/fx/qfxflipable.cpp1
-rw-r--r--src/declarative/fx/qfxitem.cpp105
-rw-r--r--src/declarative/fx/qfxitem.h5
-rw-r--r--src/declarative/fx/qfxitem_p.h4
8 files changed, 344 insertions, 537 deletions
diff --git a/demos/declarative/flickr/content/ImageDetails.qml b/demos/declarative/flickr/content/ImageDetails.qml
index b8091f2..ccc91cb 100644
--- a/demos/declarative/flickr/content/ImageDetails.qml
+++ b/demos/declarative/flickr/content/ImageDetails.qml
@@ -89,7 +89,6 @@ Flipable {
// Center image if it is smaller than the flickable area.
x: ImageContainer.width > width*scale ? (ImageContainer.width - width*scale) / 2 : 0
y: ImageContainer.height > height*scale ? (ImageContainer.height - height*scale) / 2 : 0
- anchors.centeredIn: parent
onStatusChanged : {
// Default scale shows the entire image.
if (status == 0 && width != 0) {
diff --git a/src/declarative/fx/qfxanchors.cpp b/src/declarative/fx/qfxanchors.cpp
index 53d0187..826d6c1 100644
--- a/src/declarative/fx/qfxanchors.cpp
+++ b/src/declarative/fx/qfxanchors.cpp
@@ -41,6 +41,7 @@
#include "qfxanchors_p.h"
#include "qfxitem.h"
+#include "qfxitem_p.h"
#include <QDebug>
#include <QtDeclarative/qmlinfo.h>
#include <QtDeclarative/qmlbindablevalue.h>
@@ -132,22 +133,174 @@ static qreal adjustedPosition(QFxItem *item, QFxAnchorLine::AnchorLine anchorLin
QFxAnchors::QFxAnchors(QObject *parent)
: QObject(*new QFxAnchorsPrivate(), parent)
{
-
}
-void QFxAnchors::fillChanged()
+QFxAnchors::~QFxAnchors()
{
Q_D(QFxAnchors);
- if (!d->fill)
+ d->remDepend(d->fill);
+ d->remDepend(d->centeredIn);
+ d->remDepend(d->left.item);
+ d->remDepend(d->right.item);
+ d->remDepend(d->top.item);
+ d->remDepend(d->bottom.item);
+ d->remDepend(d->vCenter.item);
+ d->remDepend(d->hCenter.item);
+}
+
+void QFxAnchorsPrivate::fillChanged()
+{
+ if (!fill || !isItemComplete())
+ return;
+
+ if (fill == item->itemParent()) { //child-parent
+ setItemPos(QPointF(leftMargin, topMargin));
+ } else if (fill->itemParent() == item->itemParent()) { //siblings
+ setItemPos(QPointF(fill->x()+leftMargin, fill->y()+topMargin));
+ }
+ setItemWidth(fill->width()-leftMargin-rightMargin);
+ setItemHeight(fill->height()-topMargin-bottomMargin);
+}
+
+void QFxAnchorsPrivate::centeredInChanged()
+{
+ if (!centeredIn || fill || !isItemComplete())
return;
- if (d->fill == d->item->itemParent()) { //child-parent
- d->item->setPos(QPointF(leftMargin(), topMargin()));
- } else if (d->fill->itemParent() == d->item->itemParent()) { //siblings
- d->item->setPos(QPointF(d->fill->x()+leftMargin(), d->fill->y()+topMargin()));
+ if (centeredIn == item->itemParent()) {
+ QPointF p((item->itemParent()->width() - item->width()) / 2.,
+ (item->itemParent()->height() - item->height()) / 2.);
+ setItemPos(p);
+
+ } else if (centeredIn->itemParent() == item->itemParent()) {
+
+ QPointF p(centeredIn->x() + (centeredIn->width() - item->width()) / 2.,
+ centeredIn->y() + (centeredIn->height() - item->height()) / 2.);
+ setItemPos(p);
+ }
+}
+
+void QFxAnchorsPrivate::clearItem(QFxItem *item)
+{
+ if (fill == item)
+ fill = 0;
+ if (centeredIn == item)
+ centeredIn = 0;
+ if (left.item == item)
+ left.item = 0;
+ if (right.item == item) {
+ right.item = 0;
+ usedAnchors &= ~QFxAnchors::HasRightAnchor;
+ }
+ if (top.item == item) {
+ top.item = 0;
+ usedAnchors &= ~QFxAnchors::HasTopAnchor;
+ }
+ if (bottom.item == item) {
+ bottom.item = 0;
+ usedAnchors &= ~QFxAnchors::HasBottomAnchor;
+ }
+ if (vCenter.item == item) {
+ vCenter.item = 0;
+ usedAnchors &= ~QFxAnchors::HasVCenterAnchor;
+ }
+ if (hCenter.item == item) {
+ hCenter.item = 0;
+ usedAnchors &= ~QFxAnchors::HasHCenterAnchor;
+ }
+}
+
+void QFxAnchorsPrivate::addDepend(QFxItem *item)
+{
+ Q_Q(QFxAnchors);
+ if (!item)
+ return;
+ QFxItemPrivate *p =
+ static_cast<QFxItemPrivate *>(QObjectPrivate::get(item));
+ p->dependantAnchors.append(q);
+}
+
+void QFxAnchorsPrivate::remDepend(QFxItem *item)
+{
+ Q_Q(QFxAnchors);
+ if (!item)
+ return;
+ QFxItemPrivate *p =
+ static_cast<QFxItemPrivate *>(QObjectPrivate::get(item));
+ p->dependantAnchors.removeAll(q);
+}
+
+bool QFxAnchorsPrivate::isItemComplete() const
+{
+ return true;
+ return item->isComponentComplete();
+}
+
+void QFxAnchorsPrivate::setItemHeight(qreal v)
+{
+ updatingMe = true;
+ item->setHeight(v);
+ updatingMe = false;
+}
+
+void QFxAnchorsPrivate::setItemWidth(qreal v)
+{
+ updatingMe = true;
+ item->setWidth(v);
+ updatingMe = false;
+}
+
+void QFxAnchorsPrivate::setItemX(qreal v)
+{
+ updatingMe = true;
+ item->setX(v);
+ updatingMe = false;
+}
+
+void QFxAnchorsPrivate::setItemY(qreal v)
+{
+ updatingMe = true;
+ item->setY(v);
+ updatingMe = false;
+}
+
+void QFxAnchorsPrivate::setItemPos(const QPointF &v)
+{
+ updatingMe = true;
+ item->setPos(v);
+ updatingMe = false;
+}
+
+void QFxAnchorsPrivate::updateMe()
+{
+ if (updatingMe) {
+ updatingMe = false;
+ return;
}
- d->item->setWidth(d->fill->width()-leftMargin()-rightMargin());
- d->item->setHeight(d->fill->height()-topMargin()-bottomMargin());
+
+ fillChanged();
+ centeredInChanged();
+ updateHorizontalAnchors();
+ updateVerticalAnchors();
+}
+
+void QFxAnchorsPrivate::updateOnComplete()
+{
+ fillChanged();
+ centeredInChanged();
+ updateHorizontalAnchors();
+ updateVerticalAnchors();
+}
+
+void QFxAnchorsPrivate::update(QFxItem *, const QRectF &newG, const QRectF &oldG)
+{
+ fillChanged();
+ centeredInChanged();
+
+ if (newG.x() != oldG.x() || newG.width() != oldG.width())
+ updateHorizontalAnchors();
+ if (newG.y() != oldG.y() || newG.height() != oldG.height())
+ updateVerticalAnchors();
}
/*!
@@ -166,37 +319,11 @@ QFxItem *QFxAnchors::fill() const
void QFxAnchors::setFill(QFxItem *f)
{
Q_D(QFxAnchors);
- if (d->fill) {
- QObject::disconnect(d->fill, SIGNAL(leftChanged()), this, SLOT(fillChanged()));
- QObject::disconnect(d->fill, SIGNAL(topChanged()), this, SLOT(fillChanged()));
- QObject::disconnect(d->fill, SIGNAL(widthChanged()), this, SLOT(fillChanged()));
- QObject::disconnect(d->fill, SIGNAL(heightChanged()), this, SLOT(fillChanged()));
- QObject::disconnect(this, SIGNAL(leftMarginChanged()), this, SLOT(fillChanged()));
- QObject::disconnect(this, SIGNAL(topMarginChanged()), this, SLOT(fillChanged()));
- QObject::disconnect(this, SIGNAL(rightMarginChanged()), this, SLOT(fillChanged()));
- QObject::disconnect(this, SIGNAL(bottomMarginChanged()), this, SLOT(fillChanged()));
- }
-
+ d->remDepend(d->fill);
d->fill = f;
+ d->addDepend(d->fill);
- if (d->fill) {
- if (d->fill == d->item->itemParent()) { //child-parent
- QObject::connect(d->fill, SIGNAL(widthChanged()), this, SLOT(fillChanged()));
- QObject::connect(d->fill, SIGNAL(heightChanged()), this, SLOT(fillChanged()));
- } else if (f->itemParent() == d->item->itemParent()) { //siblings
- QObject::connect(d->fill, SIGNAL(leftChanged()), this, SLOT(fillChanged()));
- QObject::connect(d->fill, SIGNAL(topChanged()), this, SLOT(fillChanged()));
- QObject::connect(d->fill, SIGNAL(widthChanged()), this, SLOT(fillChanged()));
- QObject::connect(d->fill, SIGNAL(heightChanged()), this, SLOT(fillChanged()));
- } else {
- qmlInfo(d->item) << "Can't anchor to an item that isn't a parent or sibling.";
- }
- }
- QObject::connect(this, SIGNAL(leftMarginChanged()), this, SLOT(fillChanged()));
- QObject::connect(this, SIGNAL(topMarginChanged()), this, SLOT(fillChanged()));
- QObject::connect(this, SIGNAL(rightMarginChanged()), this, SLOT(fillChanged()));
- QObject::connect(this, SIGNAL(bottomMarginChanged()), this, SLOT(fillChanged()));
- fillChanged(); //### can/should we defer until component completion?
+ d->fillChanged();
}
/*!
@@ -223,163 +350,12 @@ void QFxAnchors::setCenteredIn(QFxItem* c)
qmlInfo(d->item) << "Can't anchor to an item that isn't a parent or sibling.";
return;
}
- d->centeredIn = c;
- setHorizontalCenter(c->horizontalCenter());
- setVerticalCenter(c->verticalCenter());
-}
-
-void QFxAnchorsPrivate::connectVHelper(const QFxAnchorLine &edge)
-{
- //### should we do disconnects first? (will it be called more than once?)
- Q_Q(QFxAnchors);
- if (edge.item == item->itemParent()) { //child-parent
- switch(edge.anchorLine) {
- case QFxAnchorLine::Bottom:
- case QFxAnchorLine::VCenter:
- QObject::connect(edge.item, SIGNAL(heightChanged()), q, SLOT(updateVerticalAnchors()));
- break;
- case QFxAnchorLine::Top: //no connection needed
- default:
- break;
- }
- } else if (edge.item->itemParent() == item->itemParent()) { //siblings
- switch(edge.anchorLine) {
- case QFxAnchorLine::Top:
- QObject::connect(edge.item, SIGNAL(topChanged()), q, SLOT(updateVerticalAnchors()));
- break;
- case QFxAnchorLine::Bottom:
- QObject::connect(edge.item, SIGNAL(bottomChanged()), q, SLOT(updateVerticalAnchors()));
- break;
- case QFxAnchorLine::VCenter:
- QObject::connect(edge.item, SIGNAL(vcenterChanged()), q, SLOT(updateVerticalAnchors()));
- break;
- default:
- break;
- }
- } else {
- qmlInfo(item) << "Can't anchor to an item that isn't a parent or sibling.";
- }
-}
-
-void QFxAnchors::connectVAnchors()
-{
- Q_D(QFxAnchors);
- if (!d->checkVValid())
- return;
-
- if (d->usedAnchors & HasTopAnchor) {
- //Handle stretching connections (if we have multiple horizontal anchors)
- QFxAnchorLine *edge = 0;
- if (d->usedAnchors & HasBottomAnchor) {
- edge = &d->bottom;
- connect(this, SIGNAL(bottomMarginChanged()), this, SLOT(updateVerticalAnchors()));
- } else if (d->usedAnchors & HasVCenterAnchor) {
- edge = &d->vCenter;
- connect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors()));
- }
- if (edge) {
- //we need to stretch
- d->connectVHelper(*edge);
- }
-
- //Handle top
- d->connectVHelper(d->top);
- connect(this, SIGNAL(topMarginChanged()), this, SLOT(updateVerticalAnchors()));
- updateVerticalAnchors();
- } else if (d->usedAnchors & HasBottomAnchor) {
- //Handle stretching connections (if we have multiple horizontal anchors)
- if (d->usedAnchors & HasVCenterAnchor) {
- d->connectVHelper(d->vCenter);
- connect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors()));
- }
-
- //Handle bottom
- d->connectVHelper(d->bottom);
- connect(this, SIGNAL(bottomMarginChanged()), this, SLOT(updateVerticalAnchors()));
- updateVerticalAnchors();
- } else if (d->usedAnchors & HasVCenterAnchor) {
- //Handle vCenter
- d->connectVHelper(d->vCenter);
- connect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors()));
- updateVerticalAnchors();
- }
-}
-
-void QFxAnchorsPrivate::connectHHelper(const QFxAnchorLine &edge)
-{
- //### should we do disconnects first? (will it be called more than once?)
- Q_Q(QFxAnchors);
- if (edge.item == item->itemParent()) { //child-parent
- switch(edge.anchorLine) {
- case QFxAnchorLine::Right:
- case QFxAnchorLine::HCenter:
- QObject::connect(edge.item, SIGNAL(widthChanged()), q, SLOT(updateHorizontalAnchors()));
- break;
- case QFxAnchorLine::Left: //no connection needed
- default:
- break;
- }
- } else if (edge.item->itemParent() == item->itemParent()) { //siblings
- switch(edge.anchorLine) {
- case QFxAnchorLine::Left:
- QObject::connect(edge.item, SIGNAL(leftChanged()), q, SLOT(updateHorizontalAnchors()));
- break;
- case QFxAnchorLine::Right:
- QObject::connect(edge.item, SIGNAL(rightChanged()), q, SLOT(updateHorizontalAnchors()));
- break;
- case QFxAnchorLine::HCenter:
- QObject::connect(edge.item, SIGNAL(hcenterChanged()), q, SLOT(updateHorizontalAnchors()));
- break;
- default:
- break;
- }
- } else {
- qmlInfo(item) << "Can't anchor to an item that isn't a parent or sibling.";
- }
-}
-
-void QFxAnchors::connectHAnchors()
-{
- Q_D(QFxAnchors);
- if (!d->checkHValid())
- return;
-
- if (d->usedAnchors & HasLeftAnchor) {
- //Handle stretching connections (if we have multiple horizontal anchors)
- QFxAnchorLine *edge = 0;
- if (d->usedAnchors & HasRightAnchor) {
- edge = &d->right;
- connect(this, SIGNAL(rightMarginChanged()), this, SLOT(updateHorizontalAnchors()));
- } else if (d->usedAnchors & HasHCenterAnchor) {
- edge = &d->hCenter;
- connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors()));
- }
- if (edge) {
- //we need to stretch
- d->connectHHelper(*edge);
- }
- //Handle left
- d->connectHHelper(d->left);
- connect(this, SIGNAL(leftMarginChanged()), this, SLOT(updateHorizontalAnchors()));
- updateHorizontalAnchors();
- } else if (d->usedAnchors & HasRightAnchor) {
- //Handle stretching connections (if we have multiple horizontal anchors)
- if (d->usedAnchors & HasHCenterAnchor) {
- d->connectHHelper(d->hCenter);
- connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors()));
- }
+ d->remDepend(d->centeredIn);
+ d->centeredIn = c;
+ d->addDepend(d->centeredIn);
- //Handle right
- d->connectHHelper(d->right);
- connect(this, SIGNAL(rightMarginChanged()), this, SLOT(updateHorizontalAnchors()));
- updateHorizontalAnchors();
- } else if (d->usedAnchors & HasHCenterAnchor) {
- //Handle hCenter
- d->connectHHelper(d->hCenter);
- connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors()));
- updateHorizontalAnchors();
- }
+ d->centeredInChanged();
}
bool QFxAnchorsPrivate::calcStretch(const QFxAnchorLine &edge1,
@@ -411,168 +387,124 @@ bool QFxAnchorsPrivate::calcStretch(const QFxAnchorLine &edge1,
return invalid;
}
-void QFxAnchors::updateVerticalAnchors()
+void QFxAnchorsPrivate::updateVerticalAnchors()
{
- Q_D(QFxAnchors);
- if (!d->updatingVerticalAnchor) {
- d->updatingVerticalAnchor = true;
- if (d->usedAnchors & HasTopAnchor) {
+ if (fill || centeredIn || !isItemComplete())
+ return;
+
+ if (!updatingVerticalAnchor) {
+ updatingVerticalAnchor = true;
+ if (usedAnchors & QFxAnchors::HasTopAnchor) {
//Handle stretching
bool invalid = true;
int height = 0;
- if (d->usedAnchors & HasBottomAnchor) {
- invalid = d->calcStretch(d->top, d->bottom, d->topMargin, -d->bottomMargin, QFxAnchorLine::Top, height);
- } else if (d->usedAnchors & HasVCenterAnchor) {
- invalid = d->calcStretch(d->top, d->vCenter, d->topMargin, d->vCenterOffset, QFxAnchorLine::Top, height);
+ if (usedAnchors & QFxAnchors::HasBottomAnchor) {
+ invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QFxAnchorLine::Top, height);
+ } else if (usedAnchors & QFxAnchors::HasVCenterAnchor) {
+ invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QFxAnchorLine::Top, height);
height *= 2;
}
if (!invalid)
- d->item->setHeight(height);
+ setItemHeight(height);
//Handle top
- if (d->top.item == d->item->itemParent()) {
- d->item->setY(adjustedPosition(d->top.item, d->top.anchorLine) + d->topMargin);
- } else if (d->top.item->itemParent() == d->item->itemParent()) {
- d->item->setY(position(d->top.item, d->top.anchorLine) + d->topMargin);
+ if (top.item == item->itemParent()) {
+ setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin);
+ } else if (top.item->itemParent() == item->itemParent()) {
+ setItemY(position(top.item, top.anchorLine) + topMargin);
}
- } else if (d->usedAnchors & HasBottomAnchor) {
+ } else if (usedAnchors & QFxAnchors::HasBottomAnchor) {
//Handle stretching (top + bottom case is handled above)
- if (d->usedAnchors & HasVCenterAnchor) {
+ if (usedAnchors & QFxAnchors::HasVCenterAnchor) {
int height = 0;
- bool invalid = d->calcStretch(d->vCenter, d->bottom, d->vCenterOffset, -d->bottomMargin,
+ bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin,
QFxAnchorLine::Top, height);
if (!invalid)
- d->item->setHeight(height*2);
+ setItemHeight(height*2);
}
//Handle bottom
- if (d->bottom.item == d->item->itemParent()) {
- d->item->setY(adjustedPosition(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin);
- } else if (d->bottom.item->itemParent() == d->item->itemParent()) {
- d->item->setY(position(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin);
+ if (bottom.item == item->itemParent()) {
+ setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
+ } else if (bottom.item->itemParent() == item->itemParent()) {
+ setItemY(position(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
}
- } else if (d->usedAnchors & HasVCenterAnchor) {
+ } else if (usedAnchors & QFxAnchors::HasVCenterAnchor) {
//(stetching handled above)
//Handle vCenter
- if (d->vCenter.item == d->item->itemParent()) {
- d->item->setY(adjustedPosition(d->vCenter.item, d->vCenter.anchorLine)
- - d->item->height()/2 + d->vCenterOffset);
- } else if (d->vCenter.item->itemParent() == d->item->itemParent()) {
- d->item->setY(position(d->vCenter.item, d->vCenter.anchorLine) - d->item->height()/2 + d->vCenterOffset);
+ if (vCenter.item == item->itemParent()) {
+ setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine)
+ - item->height()/2 + vCenterOffset);
+ } else if (vCenter.item->itemParent() == item->itemParent()) {
+ setItemY(position(vCenter.item, vCenter.anchorLine) - item->height()/2 + vCenterOffset);
}
}
- d->updatingVerticalAnchor = false;
+ updatingVerticalAnchor = false;
} else {
- qmlInfo(d->item) << "Anchor loop detected on vertical anchor.";
+ // ### Make this certain :)
+ qmlInfo(item) << "Possible anchor loop detected on vertical anchor.";
}
}
-void QFxAnchors::updateHorizontalAnchors()
+void QFxAnchorsPrivate::updateHorizontalAnchors()
{
- Q_D(QFxAnchors);
- if (!d->updatingHorizontalAnchor) {
- d->updatingHorizontalAnchor = true;
+ if (fill || centeredIn || !isItemComplete())
+ return;
- //alternate implementation (needs performance testing)
- /*switch(d->usedAnchors & QFxAnchors::Horizontal_Mask) {
- case 0x03: //(HasLeftAnchor | HasRightAnchor)
- {
- int width = 0;
- if (!d->calcStretch(d->left, d->right, d->leftMargin, -d->rightMargin, QFxAnchorLine::Left, width))
- d->item->setWidth(width);
- //fall though
- }
- case 0x11: //(HasLeftAnchor | HasHCenterAnchor)
- {
- if (d->usedAnchors & HasHCenterAnchor) {
- int width = 0;
- if (!d->calcStretch(d->left, d->hCenter, d->leftMargin, d->hCenterOffset, QFxAnchorLine::Left, width))
- d->item->setWidth(width*2);
- }
- //fall though
- }
- case HasLeftAnchor:
- if (d->left.item == d->item->itemParent()) {
- d->item->setX(adjustedPosition(d->left.item, d->left.anchorLine) + d->leftMargin);
- } else if (d->left.item->itemParent() == d->item->itemParent()) {
- d->item->setX(position(d->left.item, d->left.anchorLine) + d->leftMargin);
- }
- break;
- case 0x12: //(HasRightAnchor | HasHCenterAnchor)
- {
- int width = 0;
- if (!d->calcStretch(d->hCenter, d->right, d->hCenterOffset, -d->rightMargin, QFxAnchorLine::Left, width))
- d->item->setWidth(width*2);
- //fall though
- }
- case HasRightAnchor:
- if (d->right.item == d->item->itemParent()) {
- d->item->setX(adjustedPosition(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin);
- } else if (d->right.item->itemParent() == d->item->itemParent()) {
- d->item->setX(position(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin);
- }
- break;
- case HasHCenterAnchor:
- if (d->hCenter.item == d->item->itemParent()) {
- d->item->setX(adjustedPosition(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset);
- } else if (d->hCenter.item->itemParent() == d->item->itemParent()) {
- d->item->setX(position(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset);
- }
- break;
- default:
- break;
- }*/
+ if (!updatingHorizontalAnchor) {
+ updatingHorizontalAnchor = true;
- if (d->usedAnchors & HasLeftAnchor) {
+ if (usedAnchors & QFxAnchors::HasLeftAnchor) {
//Handle stretching
bool invalid = true;
int width = 0;
- if (d->usedAnchors & HasRightAnchor) {
- invalid = d->calcStretch(d->left, d->right, d->leftMargin, -d->rightMargin, QFxAnchorLine::Left, width);
- } else if (d->usedAnchors & HasHCenterAnchor) {
- invalid = d->calcStretch(d->left, d->hCenter, d->leftMargin, d->hCenterOffset, QFxAnchorLine::Left, width);
+ if (usedAnchors & QFxAnchors::HasRightAnchor) {
+ invalid = calcStretch(left, right, leftMargin, -rightMargin, QFxAnchorLine::Left, width);
+ } else if (usedAnchors & QFxAnchors::HasHCenterAnchor) {
+ invalid = calcStretch(left, hCenter, leftMargin, hCenterOffset, QFxAnchorLine::Left, width);
width *= 2;
}
if (!invalid)
- d->item->setWidth(width);
+ setItemWidth(width);
//Handle left
- if (d->left.item == d->item->itemParent()) {
- d->item->setX(adjustedPosition(d->left.item, d->left.anchorLine) + d->leftMargin);
- } else if (d->left.item->itemParent() == d->item->itemParent()) {
- d->item->setX(position(d->left.item, d->left.anchorLine) + d->leftMargin);
+ if (left.item == item->itemParent()) {
+ setItemX(adjustedPosition(left.item, left.anchorLine) + leftMargin);
+ } else if (left.item->itemParent() == item->itemParent()) {
+ setItemX(position(left.item, left.anchorLine) + leftMargin);
}
- } else if (d->usedAnchors & HasRightAnchor) {
+ } else if (usedAnchors & QFxAnchors::HasRightAnchor) {
//Handle stretching (left + right case is handled in updateLeftAnchor)
- if (d->usedAnchors & HasHCenterAnchor) {
+ if (usedAnchors & QFxAnchors::HasHCenterAnchor) {
int width = 0;
- bool invalid = d->calcStretch(d->hCenter, d->right, d->hCenterOffset, -d->rightMargin,
+ bool invalid = calcStretch(hCenter, right, hCenterOffset, -rightMargin,
QFxAnchorLine::Left, width);
if (!invalid)
- d->item->setWidth(width*2);
+ setItemWidth(width*2);
}
//Handle right
- if (d->right.item == d->item->itemParent()) {
- d->item->setX(adjustedPosition(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin);
- } else if (d->right.item->itemParent() == d->item->itemParent()) {
- d->item->setX(position(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin);
+ if (right.item == item->itemParent()) {
+ setItemX(adjustedPosition(right.item, right.anchorLine) - item->width() - rightMargin);
+ } else if (right.item->itemParent() == item->itemParent()) {
+ setItemX(position(right.item, right.anchorLine) - item->width() - rightMargin);
}
- } else if (d->usedAnchors & HasHCenterAnchor) {
+ } else if (usedAnchors & QFxAnchors::HasHCenterAnchor) {
//Handle hCenter
- if (d->hCenter.item == d->item->itemParent()) {
- d->item->setX(adjustedPosition(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset);
- } else if (d->hCenter.item->itemParent() == d->item->itemParent()) {
- d->item->setX(position(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset);
+ if (hCenter.item == item->itemParent()) {
+ setItemX(adjustedPosition(hCenter.item, hCenter.anchorLine) - item->width()/2 + hCenterOffset);
+ } else if (hCenter.item->itemParent() == item->itemParent()) {
+ setItemX(position(hCenter.item, hCenter.anchorLine) - item->width()/2 + hCenterOffset);
}
}
- d->updatingHorizontalAnchor = false;
+ updatingHorizontalAnchor = false;
} else {
- qmlInfo(d->item) << "Anchor loop detected on horizontal anchor.";
+ // ### Make this certain :)
+ qmlInfo(item) << "Possible anchor loop detected on horizontal anchor.";
}
}
@@ -588,29 +520,22 @@ void QFxAnchors::setTop(const QFxAnchorLine &edge)
if (!d->checkVAnchorValid(edge))
return;
- d->usedAnchors |= HasTopAnchor;
+ if (edge.item)
+ d->usedAnchors |= HasTopAnchor;
+ else
+ d->usedAnchors &= ~HasTopAnchor;
d->checkVValid();
+ d->remDepend(d->top.item);
d->top = edge;
+ d->addDepend(d->top.item);
+ d->updateVerticalAnchors();
}
void QFxAnchors::resetTop()
{
- Q_D(QFxAnchors);
-
- //update flags
- d->usedAnchors &= ~HasTopAnchor;
-
- //clear binding
- QmlMetaProperty prop(this, "top");
- prop.binding()->clearExpression();
-
- //disconnect signal/slot connections as needed
- disconnect(this, SIGNAL(topMarginChanged()), this, SLOT(updateVerticalAnchors()));
- disconnect(d->top.item, 0, this, 0);
-
- updateVerticalAnchors();
+ setTop(QFxAnchorLine());
}
QFxAnchorLine QFxAnchors::bottom() const
@@ -625,29 +550,22 @@ void QFxAnchors::setBottom(const QFxAnchorLine &edge)
if (!d->checkVAnchorValid(edge))
return;
- d->usedAnchors |= HasBottomAnchor;
+ if (edge.item)
+ d->usedAnchors |= HasBottomAnchor;
+ else
+ d->usedAnchors &= ~HasBottomAnchor;
d->checkVValid();
+ d->remDepend(d->bottom.item);
d->bottom = edge;
+ d->addDepend(d->bottom.item);
+ d->updateVerticalAnchors();
}
void QFxAnchors::resetBottom()
{
- Q_D(QFxAnchors);
-
- //update flags
- d->usedAnchors &= ~HasBottomAnchor;
-
- //clear binding
- QmlMetaProperty prop(this, "bottom");
- prop.binding()->clearExpression();
-
- //disconnect signal/slot connections as needed
- disconnect(this, SIGNAL(bottomMarginChanged()), this, SLOT(updateVerticalAnchors()));
- disconnect(d->bottom.item, 0, this, 0);
-
- updateVerticalAnchors();
+ setBottom(QFxAnchorLine());
}
QFxAnchorLine QFxAnchors::verticalCenter() const
@@ -662,29 +580,22 @@ void QFxAnchors::setVerticalCenter(const QFxAnchorLine &edge)
if (!d->checkVAnchorValid(edge))
return;
- d->usedAnchors |= HasVCenterAnchor;
+ if (edge.item)
+ d->usedAnchors |= HasVCenterAnchor;
+ else
+ d->usedAnchors &= ~HasVCenterAnchor;
d->checkVValid();
+ d->remDepend(d->vCenter.item);
d->vCenter = edge;
+ d->addDepend(d->vCenter.item);
+ d->updateVerticalAnchors();
}
void QFxAnchors::resetVerticalCenter()
{
- Q_D(QFxAnchors);
-
- //update flags
- d->usedAnchors &= ~HasVCenterAnchor;
-
- //clear binding
- QmlMetaProperty prop(this, "verticalCenter");
- prop.binding()->clearExpression();
-
- //disconnect signal/slot connections as needed
- disconnect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors()));
- disconnect(d->vCenter.item, 0, this, 0);
-
- updateVerticalAnchors();
+ setVerticalCenter(QFxAnchorLine());
}
QFxAnchorLine QFxAnchors::left() const
@@ -699,29 +610,22 @@ void QFxAnchors::setLeft(const QFxAnchorLine &edge)
if (!d->checkHAnchorValid(edge))
return;
- d->usedAnchors |= HasLeftAnchor;
+ if (edge.item)
+ d->usedAnchors |= HasLeftAnchor;
+ else
+ d->usedAnchors &= ~HasLeftAnchor;
d->checkHValid();
+ d->remDepend(d->left.item);
d->left = edge;
+ d->addDepend(d->left.item);
+ d->updateHorizontalAnchors();
}
void QFxAnchors::resetLeft()
{
- Q_D(QFxAnchors);
-
- //update flags
- d->usedAnchors &= ~HasLeftAnchor;
-
- //clear binding
- QmlMetaProperty prop(this, "left");
- prop.binding()->clearExpression();
-
- //disconnect signal/slot connections as needed
- disconnect(this, SIGNAL(leftMarginChanged()), this, SLOT(updateHorizontalAnchors()));
- disconnect(d->left.item, 0, this, 0);
-
- updateHorizontalAnchors();
+ setLeft(QFxAnchorLine());
}
QFxAnchorLine QFxAnchors::right() const
@@ -736,29 +640,23 @@ void QFxAnchors::setRight(const QFxAnchorLine &edge)
if (!d->checkHAnchorValid(edge))
return;
- d->usedAnchors |= HasRightAnchor;
+ if (edge.item)
+ d->usedAnchors |= HasRightAnchor;
+ else
+ d->usedAnchors &= ~HasRightAnchor;
d->checkHValid();
+ d->remDepend(d->right.item);
d->right = edge;
+ d->addDepend(d->right.item);
+
+ d->updateHorizontalAnchors();
}
void QFxAnchors::resetRight()
{
- Q_D(QFxAnchors);
-
- //update flags
- d->usedAnchors &= ~HasRightAnchor;
-
- //clear binding
- QmlMetaProperty prop(this, "right");
- prop.binding()->clearExpression();
-
- //disconnect signal/slot connections as needed
- disconnect(this, SIGNAL(rightMarginChanged()), this, SLOT(updateHorizontalAnchors()));
- disconnect(d->right.item, 0, this, 0);
-
- updateHorizontalAnchors();
+ setRight(QFxAnchorLine());
}
QFxAnchorLine QFxAnchors::horizontalCenter() const
@@ -773,29 +671,22 @@ void QFxAnchors::setHorizontalCenter(const QFxAnchorLine &edge)
if (!d->checkHAnchorValid(edge))
return;
- d->usedAnchors |= HasHCenterAnchor;
+ if (edge.item)
+ d->usedAnchors |= HasHCenterAnchor;
+ else
+ d->usedAnchors &= ~HasHCenterAnchor;
d->checkHValid();
+ d->remDepend(d->hCenter.item);
d->hCenter = edge;
+ d->addDepend(d->hCenter.item);
+ d->updateHorizontalAnchors();
}
void QFxAnchors::resetHorizontalCenter()
{
- Q_D(QFxAnchors);
-
- //update flags
- d->usedAnchors &= ~HasHCenterAnchor;
-
- //clear binding
- QmlMetaProperty prop(this, "horizontalCenter");
- prop.binding()->clearExpression();
-
- //disconnect signal/slot connections as needed
- disconnect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors()));
- disconnect(d->hCenter.item, 0, this, 0);
-
- updateHorizontalAnchors();
+ setHorizontalCenter(QFxAnchorLine());
}
int QFxAnchors::leftMargin() const
@@ -888,50 +779,6 @@ void QFxAnchors::setVerticalCenterOffset(int offset)
emit verticalCenterOffsetChanged();
}
-#if 0
-/*!
- \property QFxAnchors::baseline
- \brief what the baseline of the item should be anchored to (aligned with).
-
- The baseline of a Text item is the imaginary line on which the text sits. Controls containing
- text usually set their baseline to the baseline of their text.
-
- For non-text items, a default baseline offset of two-thirds of the item's height is used
- to determine the baseline.
-*/
-int QFxAnchors::baseline() const
-{
- return d->item->baseline();
-}
-
-void QFxAnchors::setBaseline(int baseline)
-{
- d->usedAnchors |= HasBaselineAnchor;
-
- if (d->usedAnchors & HasTopAnchor && d->usedAnchors & HasBottomAnchor) {
- qmlInfo(d->item) << "Can't specify top, bottom, and baseline anchors";
- return;
- }
-
- if (d->usedAnchors & HasTopAnchor) {
- int hoffset = baseline - d->item->baseline();
- d->item->setHeight(d->item->height() + hoffset);
- } else {
- if (d->usedAnchors & HasBottomAnchor) {
- int hoffset = d->item->baseline() - baseline;
- d->item->setHeight(d->item->height() + hoffset);
- }
-
- int boffset = d->item->baseline() - d->item->top();
- QFxItem *parentItem = d->item->itemParent();
- if (parentItem)
- d->item->setY(baseline - boffset - parentItem->top());
- else
- d->item->setY(baseline - boffset);
- }
-}
-#endif
-
QFxAnchors::UsedAnchors QFxAnchors::usedAnchors() const
{
Q_D(const QFxAnchors);
diff --git a/src/declarative/fx/qfxanchors.h b/src/declarative/fx/qfxanchors.h
index 5a8cc1a..2c59266 100644
--- a/src/declarative/fx/qfxanchors.h
+++ b/src/declarative/fx/qfxanchors.h
@@ -80,6 +80,7 @@ public:
Q_DECLARE_METATYPE(QFxAnchorLine);
+class QFxAnchorsPrivate;
class Q_DECLARATIVE_EXPORT QFxAnchors : public QObject
{
Q_OBJECT
@@ -101,6 +102,7 @@ class Q_DECLARATIVE_EXPORT QFxAnchors : public QObject
public:
QFxAnchors(QObject *parent=0);
+ virtual ~QFxAnchors();
enum UsedAnchor {
HasLeftAnchor = 0x01,
@@ -167,9 +169,6 @@ public:
void setItem(QFxItem *item);
- void connectHAnchors();
- void connectVAnchors();
-
Q_SIGNALS:
void leftMarginChanged();
void rightMarginChanged();
@@ -178,13 +177,8 @@ Q_SIGNALS:
void verticalCenterOffsetChanged();
void horizontalCenterOffsetChanged();
-private Q_SLOTS:
- void fillChanged();
- void updateHorizontalAnchors();
- void updateVerticalAnchors();
-
private:
- //### should item be a friend? (and make some of the public methods private or protected)
+ friend class QFxItem;
Q_DISABLE_COPY(QFxAnchors)
Q_DECLARE_PRIVATE(QFxAnchors)
};
diff --git a/src/declarative/fx/qfxanchors_p.h b/src/declarative/fx/qfxanchors_p.h
index 82c2086..b90380a 100644
--- a/src/declarative/fx/qfxanchors_p.h
+++ b/src/declarative/fx/qfxanchors_p.h
@@ -63,9 +63,10 @@ class QFxAnchorsPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QFxAnchors)
public:
QFxAnchorsPrivate()
- : item(0), usedAnchors(0), fill(0), centeredIn(0), leftMargin(0), rightMargin(0),
- topMargin(0), bottomMargin(0), vCenterOffset(0), hCenterOffset(0),
- updatingHorizontalAnchor(false), updatingVerticalAnchor(false)
+ : updatingMe(false), updatingHorizontalAnchor(false),
+ updatingVerticalAnchor(false), item(0), usedAnchors(0), fill(0),
+ centeredIn(0), leftMargin(0), rightMargin(0), topMargin(0),
+ bottomMargin(0), vCenterOffset(0), hCenterOffset(0)
{
}
@@ -73,14 +74,37 @@ public:
{
}
+ void clearItem(QFxItem *);
+
+ void addDepend(QFxItem *);
+ void remDepend(QFxItem *);
+ bool isItemComplete() const;
+
+ bool updatingMe:1;
+ bool updatingHorizontalAnchor:1;
+ bool updatingVerticalAnchor:1;
+
+ void setItemHeight(qreal);
+ void setItemWidth(qreal);
+ void setItemX(qreal);
+ void setItemY(qreal);
+ void setItemPos(const QPointF &);
+
+ void updateOnComplete();
+ void updateMe();
+ void update(QFxItem *, const QRectF &, const QRectF &);
+
bool checkHValid() const;
bool checkVValid() const;
bool checkHAnchorValid(QFxAnchorLine anchor) const;
bool checkVAnchorValid(QFxAnchorLine anchor) const;
- void connectHHelper(const QFxAnchorLine &anchorLine);
- void connectVHelper(const QFxAnchorLine &anchorLine);
bool calcStretch(const QFxAnchorLine &edge1, const QFxAnchorLine &edge2, int offset1, int offset2, QFxAnchorLine::AnchorLine line, int &stretch);
+ void updateHorizontalAnchors();
+ void updateVerticalAnchors();
+ void fillChanged();
+ void centeredInChanged();
+
QFxItem *item;
QFxAnchors::UsedAnchors usedAnchors;
@@ -101,8 +125,6 @@ public:
int vCenterOffset;
int hCenterOffset;
- bool updatingHorizontalAnchor;
- bool updatingVerticalAnchor;
};
QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxflipable.cpp b/src/declarative/fx/qfxflipable.cpp
index 24ae428..9804004 100644
--- a/src/declarative/fx/qfxflipable.cpp
+++ b/src/declarative/fx/qfxflipable.cpp
@@ -296,6 +296,7 @@ QFxFlipable::Side QFxFlipable::side() const
//(the logic here should be kept in sync with setBackTransform and setRotation)
void QFxFlipable::transformChanged(const QSimpleCanvas::Matrix &trans)
{
+ qWarning("Transform changed");
Q_D(QFxFlipable);
QPointF p1(0, 0);
QPointF p2(1, 0);
diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp
index b737615..3cbcd6a 100644
--- a/src/declarative/fx/qfxitem.cpp
+++ b/src/declarative/fx/qfxitem.cpp
@@ -52,6 +52,7 @@
#include "qmlengine.h"
#include "qmlstate.h"
#include "qlistmodelinterface.h"
+#include "qfxanchors_p.h"
#include "qfxtransform.h"
#include "qfxscalegrid.h"
@@ -434,6 +435,14 @@ void QFxItem::doUpdate()
QFxItem::~QFxItem()
{
Q_D(QFxItem);
+ for (int ii = 0; ii < d->dependantAnchors.count(); ++ii) {
+ QFxAnchors *anchor = d->dependantAnchors.at(ii);
+ anchor->d_func()->clearItem(this);
+ }
+ for (int ii = 0; ii < d->dependantAnchors.count(); ++ii) {
+ QFxAnchors *anchor = d->dependantAnchors.at(ii);
+ anchor->d_func()->updateOnComplete();
+ }
delete d->_anchorLines; d->_anchorLines = 0;
}
@@ -1062,85 +1071,30 @@ void QFxItem::geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry)
{
Q_D(QFxItem);
- if (newGeometry.width() != oldGeometry.width()) {
- int xoffset = oldGeometry.width() - newGeometry.width();
- d->handleWidthChange(xoffset);
- }
- if (newGeometry.height() != oldGeometry.height()) {
- int yoffset = oldGeometry.height() - newGeometry.height();
- d->handleHeightChange(yoffset);
- }
+ if (d->_anchors)
+ d->_anchors->d_func()->updateMe();
- if (newGeometry.x() != oldGeometry.x()) {
- emit leftChanged();
- emit hcenterChanged();
- emit rightChanged();
+ if (newGeometry.size() != oldGeometry.size()) {
+ if (rotation() && transformOrigin() != QFxItem::TopLeft)
+ setRotation(rotation());
+ if (scale() && transformOrigin() != QFxItem::TopLeft)
+ setScale(scale());
}
- if (newGeometry.y() != oldGeometry.y()) {
+ if (newGeometry.x() != oldGeometry.x())
+ emit leftChanged();
+ if (newGeometry.width() != oldGeometry.width())
+ emit widthChanged();
+ if (newGeometry.y() != oldGeometry.y())
emit topChanged();
- emit vcenterChanged();
- emit bottomChanged();
- }
-}
-
-void QFxItemPrivate::handleWidthChange(int xoffset)
-{
- Q_Q(QFxItem);
- if (!_anchors) {
- emit q->hcenterChanged();
- emit q->rightChanged();
- } else {
- QFxAnchors::UsedAnchors used = anchors()->usedAnchors();
- if (used & QFxAnchors::HasHCenterAnchor) {
- q->setX(q->x() + xoffset/2);
- emit q->rightChanged();
- } else if ((used & QFxAnchors::HasRightAnchor) && !(used & QFxAnchors::HasLeftAnchor)) {
- q->setX(q->x() + xoffset);
- emit q->hcenterChanged();
- } else {
- emit q->hcenterChanged();
- emit q->rightChanged();
- }
- }
- if (q->rotation() && q->transformOrigin() != QFxItem::TopLeft)
- q->setRotation(q->rotation());
- if (q->scale() && q->transformOrigin() != QFxItem::TopLeft)
- q->setScale(q->scale());
- emit q->widthChanged();
-}
+ if (newGeometry.height() != oldGeometry.height())
+ emit heightChanged();
-void QFxItemPrivate::handleHeightChange(int yoffset)
-{
- Q_Q(QFxItem);
- if (!_anchors) {
- emit q->vcenterChanged();
- emit q->bottomChanged();
- emit q->baselineChanged();
- } else {
- QFxAnchors::UsedAnchors used = anchors()->usedAnchors();
- if (used & QFxAnchors::HasBaselineAnchor) {
- q->setY(q->y() + yoffset - q->baselineOffset());
- emit q->bottomChanged();
- emit q->vcenterChanged();
- } else if (used & QFxAnchors::HasVCenterAnchor) {
- q->setY(q->y() + yoffset/2);
- emit q->bottomChanged();
- } else if ((used & QFxAnchors::HasBottomAnchor) && !(used & QFxAnchors::HasTopAnchor)) {
- q->setY(q->y() + yoffset);
- emit q->vcenterChanged();
- } else {
- emit q->vcenterChanged();
- emit q->bottomChanged();
- emit q->baselineChanged();
- }
+ for(int ii = 0; ii < d->dependantAnchors.count(); ++ii) {
+ QFxAnchors *anchor = d->dependantAnchors.at(ii);
+ anchor->d_func()->update(this, newGeometry, oldGeometry);
}
- if (q->rotation() && q->transformOrigin() != QFxItem::TopLeft)
- q->setRotation(q->rotation());
- if (q->scale() && q->transformOrigin() != QFxItem::TopLeft)
- q->setScale(q->scale());
- emit q->heightChanged();
}
/*!
@@ -1483,7 +1437,6 @@ void QFxItem::setBaselineOffset(int offset)
d->_baselineOffset = offset;
emit baselineOffsetChanged();
- emit baselineChanged();
}
/*!
@@ -2075,10 +2028,8 @@ void QFxItem::componentComplete()
d->_componentComplete = true;
if (d->_stateGroup)
d->_stateGroup->componentComplete();
- if (d->_anchors) {
- d->anchors()->connectHAnchors();
- d->anchors()->connectVAnchors();
- }
+ if (d->_anchors)
+ d->anchors()->d_func()->updateOnComplete();
if (!d->_transform.isEmpty())
updateTransform();
}
diff --git a/src/declarative/fx/qfxitem.h b/src/declarative/fx/qfxitem.h
index 549c9c2..437709f 100644
--- a/src/declarative/fx/qfxitem.h
+++ b/src/declarative/fx/qfxitem.h
@@ -213,14 +213,9 @@ public Q_SLOTS:
Q_SIGNALS:
void leftChanged();
- void rightChanged();
void widthChanged();
void heightChanged();
void topChanged();
- void bottomChanged();
- void hcenterChanged();
- void vcenterChanged();
- void baselineChanged();
void baselineOffsetChanged();
void stateChanged(const QString &);
void focusChanged();
diff --git a/src/declarative/fx/qfxitem_p.h b/src/declarative/fx/qfxitem_p.h
index f2da3ba..8ca7fda 100644
--- a/src/declarative/fx/qfxitem_p.h
+++ b/src/declarative/fx/qfxitem_p.h
@@ -129,6 +129,7 @@ public:
}
return _anchors;
}
+ QList<QFxAnchors *> dependantAnchors;
QFxAnchors *_anchors;
QFxContents *_contents;
QFxItem *qmlItem;
@@ -171,9 +172,6 @@ public:
QmlStateGroup *states();
QmlStateGroup *_stateGroup;
-
- void handleWidthChange(int xoffset);
- void handleHeightChange(int xoffset);
};
QT_END_NAMESPACE