summaryrefslogtreecommitdiffstats
path: root/src/declarative/fx/qfxanchors.cpp
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2009-04-22 04:47:24 (GMT)
committerMichael Brasser <michael.brasser@nokia.com>2009-04-22 04:47:24 (GMT)
commit2366667fc97eb6a56203b2dd7dac776ff4164abd (patch)
treeb2acb6cc6bfe475d7e619e4788973b61fff775e0 /src/declarative/fx/qfxanchors.cpp
parent2c762f3b8b284a7c6dc0c499b7052013bad5b707 (diff)
downloadQt-2366667fc97eb6a56203b2dd7dac776ff4164abd.zip
Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.gz
Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.bz2
Initial import of kinetic-dui branch from the old kinetic
Diffstat (limited to 'src/declarative/fx/qfxanchors.cpp')
-rw-r--r--src/declarative/fx/qfxanchors.cpp857
1 files changed, 857 insertions, 0 deletions
diff --git a/src/declarative/fx/qfxanchors.cpp b/src/declarative/fx/qfxanchors.cpp
new file mode 100644
index 0000000..b7a7dd2
--- /dev/null
+++ b/src/declarative/fx/qfxanchors.cpp
@@ -0,0 +1,857 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxanchors_p.h"
+#include "qfxitem.h"
+#include <QDebug>
+#include <QtDeclarative/qmlinfo.h>
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxAnchors,Anchors);
+
+//TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
+//TODO: baseline support
+//TODO: support non-parent, non-sibling (need to find lowest common ancestor)
+
+//### const item?
+//local position
+static qreal position(QFxItem *item, QFxAnchorLine::AnchorLine anchorLine)
+{
+ qreal ret = 0.0;
+ switch(anchorLine) {
+ case QFxAnchorLine::Left:
+ ret = item->x();
+ break;
+ case QFxAnchorLine::Right:
+ ret = item->x() + item->width();
+ break;
+ case QFxAnchorLine::Top:
+ ret = item->y();
+ break;
+ case QFxAnchorLine::Bottom:
+ ret = item->y() + item->height();
+ break;
+ case QFxAnchorLine::HCenter:
+ ret = item->x() + item->width()/2;
+ break;
+ case QFxAnchorLine::VCenter:
+ ret = item->y() + item->height()/2;
+ break;
+ case QFxAnchorLine::Baseline:
+ ret = item->y() + item->baselineOffset();
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+//position when origin is 0,0
+static qreal adjustedPosition(QFxItem *item, QFxAnchorLine::AnchorLine anchorLine)
+{
+ int ret = 0;
+ switch(anchorLine) {
+ case QFxAnchorLine::Left:
+ ret = 0;
+ break;
+ case QFxAnchorLine::Right:
+ ret = item->width();
+ break;
+ case QFxAnchorLine::Top:
+ ret = 0;
+ break;
+ case QFxAnchorLine::Bottom:
+ ret = item->height();
+ break;
+ case QFxAnchorLine::HCenter:
+ ret = item->width()/2;
+ break;
+ case QFxAnchorLine::VCenter:
+ ret = item->height()/2;
+ break;
+ case QFxAnchorLine::Baseline:
+ ret = item->baselineOffset();
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ \internal
+ \class QFxAnchors
+ \ingroup layouts
+ \brief The QFxAnchors class provides a way to lay out items relative to other items.
+
+ \warning Currently, only anchoring to siblings or parent is supported.
+*/
+
+QFxAnchors::QFxAnchors(QObject *parent)
+ : QObject(*new QFxAnchorsPrivate(), parent)
+{
+
+}
+
+void QFxAnchors::fillChanged()
+{
+ Q_D(QFxAnchors);
+ if (!d->fill)
+ 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()));
+ }
+ d->item->setWidth(d->fill->width()-leftMargin()-rightMargin());
+ d->item->setHeight(d->fill->height()-topMargin()-bottomMargin());
+}
+
+/*!
+ \property QFxAnchors::fill
+ \brief what item the item should fill.
+
+ This is a convenience property. It is the same as anchoring the left, right, top, and bottom
+ to another item's left, right, top, and bottom.
+*/
+QFxItem *QFxAnchors::fill() const
+{
+ Q_D(const QFxAnchors);
+ return d->fill;
+}
+
+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->fill = f;
+
+ 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?
+}
+
+/*!
+ \property QFxAnchors::centeredIn
+ \brief what item the item should stay centered in the middle of.
+
+ This is a convenience property. It is the same as anchoring the horizontalCenter
+ and verticalCenter to another item's horizontalCenter and verticalCenter.
+*/
+QFxItem *QFxAnchors::centeredIn() const
+{
+ Q_D(const QFxAnchors);
+ return d->centeredIn;
+}
+
+void QFxAnchors::setCenteredIn(QFxItem* c)
+{
+ Q_D(QFxAnchors);
+ if(!c){
+ qmlInfo(d->item) << "Cannot center in null item.";
+ return;
+ }
+ if(c != d->item->itemParent() && c->itemParent() != d->item->itemParent()){
+ 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, const char *slotString)
+{
+ //### 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, slotString);
+ 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, slotString);
+ break;
+ case QFxAnchorLine::Bottom:
+ QObject::connect(edge.item, SIGNAL(bottomChanged()), q, slotString);
+ break;
+ case QFxAnchorLine::VCenter:
+ QObject::connect(edge.item, SIGNAL(vcenterChanged()), q, slotString);
+ 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) {
+ const char *slotStr = SLOT(updateTopAnchor());
+
+ //Handle stretching connections (if we have multiple horizontal anchors)
+ QFxAnchorLine *edge = 0;
+ if (d->usedAnchors & HasBottomAnchor) {
+ edge = &d->bottom;
+ connect(this, SIGNAL(bottomMarginChanged()), this, slotStr);
+ } else if (d->usedAnchors & HasVCenterAnchor) {
+ edge = &d->vCenter;
+ connect(this, SIGNAL(verticalCenterOffsetChanged()), this, slotStr);
+ }
+ if (edge) {
+ //we need to stretch
+ d->connectVHelper(*edge, slotStr);
+ }
+
+ //Handle top
+ d->connectVHelper(d->top, slotStr);
+ connect(this, SIGNAL(topMarginChanged()), this, slotStr);
+ updateTopAnchor();
+ } else if (d->usedAnchors & HasBottomAnchor) {
+ const char *slotStr = SLOT(updateBottomAnchor());
+
+ //Handle stretching connections (if we have multiple horizontal anchors)
+ if (d->usedAnchors & HasVCenterAnchor) {
+ d->connectVHelper(d->vCenter, slotStr);
+ connect(this, SIGNAL(verticalCenterOffsetChanged()), this, slotStr);
+ }
+
+ //Handle bottom
+ d->connectVHelper(d->bottom, slotStr);
+ connect(this, SIGNAL(bottomMarginChanged()), this, slotStr);
+ updateBottomAnchor();
+ } else if (d->usedAnchors & HasVCenterAnchor) {
+ //Handle vCenter
+ const char *slotStr = SLOT(updateVCenterAnchor());
+ d->connectVHelper(d->vCenter, slotStr);
+ connect(this, SIGNAL(verticalCenterOffsetChanged()), this, slotStr);
+ updateVCenterAnchor();
+ }
+}
+
+void QFxAnchorsPrivate::connectHHelper(const QFxAnchorLine &edge, const char *slotString)
+{
+ //### 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, slotString);
+ 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, slotString);
+ break;
+ case QFxAnchorLine::Right:
+ QObject::connect(edge.item, SIGNAL(rightChanged()), q, slotString);
+ break;
+ case QFxAnchorLine::HCenter:
+ QObject::connect(edge.item, SIGNAL(hcenterChanged()), q, slotString);
+ 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) {
+ const char *slotStr = SLOT(updateLeftAnchor());
+
+ //Handle stretching connections (if we have multiple horizontal anchors)
+ QFxAnchorLine *edge = 0;
+ if (d->usedAnchors & HasRightAnchor) {
+ edge = &d->right;
+ connect(this, SIGNAL(rightMarginChanged()), this, slotStr);
+ } else if (d->usedAnchors & HasHCenterAnchor) {
+ edge = &d->hCenter;
+ connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, slotStr);
+ }
+ if (edge) {
+ //we need to stretch
+ d->connectHHelper(*edge, slotStr);
+ }
+
+ //Handle left
+ d->connectHHelper(d->left, slotStr);
+ connect(this, SIGNAL(leftMarginChanged()), this, slotStr);
+ updateLeftAnchor();
+ } else if (d->usedAnchors & HasRightAnchor) {
+ const char *slotStr = SLOT(updateRightAnchor());
+
+ //Handle stretching connections (if we have multiple horizontal anchors)
+ if (d->usedAnchors & HasHCenterAnchor) {
+ d->connectHHelper(d->hCenter, slotStr);
+ connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, slotStr);
+ }
+
+ //Handle right
+ d->connectHHelper(d->right, slotStr);
+ connect(this, SIGNAL(rightMarginChanged()), this, slotStr);
+ updateRightAnchor();
+ } else if (d->usedAnchors & HasHCenterAnchor) {
+ //Handle hCenter
+ const char *slotStr = SLOT(updateHCenterAnchor());
+ d->connectHHelper(d->hCenter, slotStr);
+ connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, slotStr);
+ updateHCenterAnchor();
+ }
+}
+
+bool QFxAnchorsPrivate::calcStretch(const QFxAnchorLine &edge1,
+ const QFxAnchorLine &edge2,
+ int offset1,
+ int offset2,
+ QFxAnchorLine::AnchorLine line,
+ int &stretch)
+{
+ bool edge1IsParent = (edge1.item == item->itemParent());
+ bool edge2IsParent = (edge2.item == item->itemParent());
+ bool edge1IsSibling = (edge1.item->itemParent() == item->itemParent());
+ bool edge2IsSibling = (edge2.item->itemParent() == item->itemParent());
+
+ bool invalid = false;
+ if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
+ stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2)
+ - ((int)position(edge1.item, edge1.anchorLine) + offset1);
+ } else if (edge2IsParent && edge1IsSibling) {
+ stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2)
+ - ((int)position(item->itemParent(), line)
+ + (int)position(edge1.item, edge1.anchorLine) + offset1);
+ } else if (edge2IsSibling && edge1IsParent) {
+ stretch = ((int)position(item->itemParent(), line) + (int)position(edge2.item, edge2.anchorLine) + offset2)
+ - ((int)position(edge1.item, edge1.anchorLine) + offset1);
+ } else
+ invalid = true;
+
+ return invalid;
+}
+
+void QFxAnchors::updateTopAnchor()
+{
+ Q_D(QFxAnchors);
+ if (d->usedAnchors & 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);
+ height *= 2;
+ }
+ if (!invalid)
+ d->item->setHeight(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);
+ }
+ }
+}
+
+void QFxAnchors::updateBottomAnchor()
+{
+ Q_D(QFxAnchors);
+ if (d->usedAnchors & HasBottomAnchor) {
+ //Handle stretching (top + bottom case is handled in updateLeftAnchor)
+ if (d->usedAnchors & HasVCenterAnchor) {
+ int height = 0;
+ bool invalid = d->calcStretch(d->vCenter, d->bottom, d->vCenterOffset, -d->bottomMargin,
+ QFxAnchorLine::Top, height);
+ if (!invalid)
+ d->item->setHeight(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);
+ }
+ }
+}
+
+void QFxAnchors::updateVCenterAnchor()
+{
+ Q_D(QFxAnchors);
+ if (d->usedAnchors & HasVCenterAnchor) {
+ //(stetching handled in other update functions)
+
+ //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);
+ }
+ }
+}
+
+void QFxAnchors::updateLeftAnchor()
+{
+ Q_D(QFxAnchors);
+ if (d->usedAnchors & 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);
+ width *= 2;
+ }
+ if (!invalid)
+ d->item->setWidth(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);
+ }
+ }
+}
+
+void QFxAnchors::updateRightAnchor()
+{
+ Q_D(QFxAnchors);
+ if (d->usedAnchors & HasRightAnchor) {
+ //Handle stretching (left + right case is handled in updateLeftAnchor)
+ if (d->usedAnchors & HasHCenterAnchor) {
+ int width = 0;
+ bool invalid = d->calcStretch(d->hCenter, d->right, d->hCenterOffset, -d->rightMargin,
+ QFxAnchorLine::Left, width);
+ if (!invalid)
+ d->item->setWidth(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);
+ }
+ }
+}
+
+void QFxAnchors::updateHCenterAnchor()
+{
+ Q_D(QFxAnchors);
+ if (d->usedAnchors & 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);
+ }
+ }
+}
+
+QFxAnchorLine QFxAnchors::top() const
+{
+ Q_D(const QFxAnchors);
+ return d->top;
+}
+
+void QFxAnchors::setTop(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkVAnchorValid(edge))
+ return;
+
+ d->usedAnchors |= HasTopAnchor;
+
+ d->checkVValid();
+
+ d->top = edge;
+}
+
+QFxAnchorLine QFxAnchors::bottom() const
+{
+ Q_D(const QFxAnchors);
+ return d->bottom;
+}
+
+void QFxAnchors::setBottom(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkVAnchorValid(edge))
+ return;
+
+ d->usedAnchors |= HasBottomAnchor;
+
+ d->checkVValid();
+
+ d->bottom = edge;
+
+}
+
+QFxAnchorLine QFxAnchors::verticalCenter() const
+{
+ Q_D(const QFxAnchors);
+ return d->vCenter;
+}
+
+void QFxAnchors::setVerticalCenter(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkVAnchorValid(edge))
+ return;
+
+ d->usedAnchors |= HasVCenterAnchor;
+
+ d->checkVValid();
+
+ d->vCenter = edge;
+}
+
+QFxAnchorLine QFxAnchors::left() const
+{
+ Q_D(const QFxAnchors);
+ return d->left;
+}
+
+void QFxAnchors::setLeft(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkHAnchorValid(edge))
+ return;
+
+ d->usedAnchors |= HasLeftAnchor;
+
+ d->checkHValid();
+
+ d->left = edge;
+}
+
+QFxAnchorLine QFxAnchors::right() const
+{
+ Q_D(const QFxAnchors);
+ return d->right;
+}
+
+void QFxAnchors::setRight(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkHAnchorValid(edge))
+ return;
+
+ d->usedAnchors |= HasRightAnchor;
+
+ d->checkHValid();
+
+ d->right = edge;
+
+}
+
+QFxAnchorLine QFxAnchors::horizontalCenter() const
+{
+ Q_D(const QFxAnchors);
+ return d->hCenter;
+}
+
+void QFxAnchors::setHorizontalCenter(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkHAnchorValid(edge))
+ return;
+
+ d->usedAnchors |= HasHCenterAnchor;
+
+ d->checkHValid();
+
+ d->hCenter = edge;
+}
+
+int QFxAnchors::leftMargin() const
+{
+ Q_D(const QFxAnchors);
+ return d->leftMargin;
+}
+
+void QFxAnchors::setLeftMargin(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->leftMargin == offset)
+ return;
+ d->leftMargin = offset;
+ emit leftMarginChanged();
+}
+
+int QFxAnchors::rightMargin() const
+{
+ Q_D(const QFxAnchors);
+ return d->rightMargin;
+}
+
+void QFxAnchors::setRightMargin(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->rightMargin == offset)
+ return;
+ d->rightMargin = offset;
+ emit rightMarginChanged();
+}
+
+int QFxAnchors::horizontalCenterOffset() const
+{
+ Q_D(const QFxAnchors);
+ return d->hCenterOffset;
+}
+
+void QFxAnchors::setHorizontalCenterOffset(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->hCenterOffset == offset)
+ return;
+ d->hCenterOffset = offset;
+ emit horizontalCenterOffsetChanged();
+}
+
+int QFxAnchors::topMargin() const
+{
+ Q_D(const QFxAnchors);
+ return d->topMargin;
+}
+
+void QFxAnchors::setTopMargin(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->topMargin == offset)
+ return;
+ d->topMargin = offset;
+ emit topMarginChanged();
+}
+
+int QFxAnchors::bottomMargin() const
+{
+ Q_D(const QFxAnchors);
+ return d->bottomMargin;
+}
+
+void QFxAnchors::setBottomMargin(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->bottomMargin == offset)
+ return;
+ d->bottomMargin = offset;
+ emit bottomMarginChanged();
+}
+
+int QFxAnchors::verticalCenterOffset() const
+{
+ Q_D(const QFxAnchors);
+ return d->vCenterOffset;
+}
+
+void QFxAnchors::setVerticalCenterOffset(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->vCenterOffset == offset)
+ return;
+ d->vCenterOffset = 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);
+ return d->usedAnchors;
+}
+
+void QFxAnchors::setItem(QFxItem *item)
+{
+ Q_D(QFxAnchors);
+ d->item = item;
+}
+
+bool QFxAnchorsPrivate::checkHValid() const
+{
+ if (usedAnchors & QFxAnchors::HasLeftAnchor &&
+ usedAnchors & QFxAnchors::HasRightAnchor &&
+ usedAnchors & QFxAnchors::HasHCenterAnchor) {
+ qmlInfo(item) << "Can't specify left, right, and hcenter anchors";
+ return false;
+ }
+
+ return true;
+}
+
+bool QFxAnchorsPrivate::checkHAnchorValid(QFxAnchorLine anchor) const
+{
+ if (anchor.anchorLine & QFxAnchorLine::Vertical_Mask) {
+ qmlInfo(item) << "Can't anchor a horizontal edge to a vertical edge.";
+ return false;
+ }else if(anchor.item == item){
+ qmlInfo(item) << "Can't anchor item to self.";
+ return false;
+ }
+
+ return true;
+}
+
+bool QFxAnchorsPrivate::checkVValid() const
+{
+ if (usedAnchors & QFxAnchors::HasTopAnchor &&
+ usedAnchors & QFxAnchors::HasBottomAnchor &&
+ usedAnchors & QFxAnchors::HasVCenterAnchor) {
+ qmlInfo(item) << "Can't specify top, bottom, and vcenter anchors";
+ return false;
+ }
+
+ return true;
+}
+
+bool QFxAnchorsPrivate::checkVAnchorValid(QFxAnchorLine anchor) const
+{
+ if (anchor.anchorLine & QFxAnchorLine::Horizontal_Mask) {
+ qmlInfo(item) << "Can't anchor a vertical edge to a horizontal edge.";
+ return false;
+ }else if(anchor.item == item){
+ qmlInfo(item) << "Can't anchor item to self.";
+ return false;
+ }
+
+ return true;
+}
+QT_END_NAMESPACE