summaryrefslogtreecommitdiffstats
path: root/src/declarative/fx/qfxitem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/fx/qfxitem.cpp')
-rw-r--r--src/declarative/fx/qfxitem.cpp1751
1 files changed, 1751 insertions, 0 deletions
diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp
new file mode 100644
index 0000000..2f4c220
--- /dev/null
+++ b/src/declarative/fx/qfxitem.cpp
@@ -0,0 +1,1751 @@
+/****************************************************************************
+**
+** 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 <QDebug>
+#include <QPen>
+#include <QFile>
+#include <QEvent>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QGraphicsSceneMouseEvent>
+#include <QtScript/qscriptengine.h>
+#include <qfxperf.h>
+
+#include "qmlengine.h"
+#include "qmlstate.h"
+#include "qlistmodelinterface.h"
+
+#include "qfxtransform.h"
+#include "qfxscalegrid.h"
+#include "qfxview.h"
+#include "qmlstategroup.h"
+
+#include "qfxitem_p.h"
+#include "qfxitem.h"
+#include <qsimplecanvasfilter.h>
+#include <qmlcomponent.h>
+
+
+QT_BEGIN_NAMESPACE
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
+
+QML_DEFINE_NOCREATE_TYPE(QFxContents);
+QML_DEFINE_TYPE(QFxItem,Item);
+QML_DEFINE_NOCREATE_TYPE(QSimpleCanvasFilter);
+
+/*!
+ \defgroup animation Animation
+ \defgroup coreitems Basic Items
+ \defgroup effects Effects
+ \defgroup layouts Layouts
+ \defgroup states States and Transitions
+ \defgroup utility Utility
+ \defgroup views Views
+ \defgroup widgets Widgets
+*/
+
+/*!
+ \internal
+ \class QFxContents
+ \ingroup utility
+ \brief The QFxContents class gives access to the height and width of an item's contents.
+
+*/
+
+QFxContents::QFxContents() : _height(0), _width(0)
+{
+}
+
+/*!
+ \property QFxContents::height
+ \brief The height of the contents.
+*/
+int QFxContents::height() const
+{
+ return _height;
+}
+
+/*!
+ \property QFxContents::width
+ \brief The width of the contents.
+*/
+int QFxContents::width() const
+{
+ return _width;
+}
+
+//TODO: optimization: only check sender(), if there is one
+void QFxContents::calcHeight()
+{
+ int oldheight = _height;
+
+ int top = INT_MAX;
+ int bottom = 0;
+ foreach(const QSimpleCanvasItem *child,
+ _item->QSimpleCanvasItem::children()) {
+ if (child->y() + child->height() > bottom)
+ bottom = (int)child->y() + child->height();
+ if (child->y() < top)
+ top = (int)child->y();
+ }
+ _height = bottom - top;
+
+ if (_height != oldheight)
+ emit heightChanged();
+}
+
+//TODO: optimization: only check sender(), if there is one
+void QFxContents::calcWidth()
+{
+ int oldwidth = _width;
+
+ int left = INT_MAX;
+ int right = 0;
+ foreach(const QSimpleCanvasItem *child,
+ _item->QSimpleCanvasItem::children()) {
+ if (child->x() + child->width() > right)
+ right = (int)child->x() + child->width();
+ if (child->x() < left)
+ left = (int)child->x();
+ }
+ _width = right - left;
+
+ if (_width != oldwidth)
+ emit widthChanged();
+}
+
+void QFxContents::setItem(QFxItem *item)
+{
+ _item = item;
+
+ foreach(const QSimpleCanvasItem *child,
+ _item->QSimpleCanvasItem::children()) {
+ connect(child, SIGNAL(bottomChanged()), this, SLOT(calcHeight()));
+ connect(child, SIGNAL(rightChanged()), this, SLOT(calcWidth()));
+ }
+
+ calcHeight();
+ calcWidth();
+}
+
+/*!
+ \qmlclass Item QFxItem
+ \brief The Item element is the most basic of all visual canvas members.
+ */
+
+/*!
+ \class QFxItem Item
+ \brief The QFxItem class is a generic QFxView item. It is the base class for all other view items.
+
+ \qmltext
+ All visual elements in Qt Declarative inherit from QFxItem. Although QFxItem
+ has no visual appearance, it defines all the properties that are
+ common across visual elements - like the x and y position, and the
+ width and height.
+
+ QFxItem is also useful for grouping elements together.
+
+ \qml
+ <Item>
+ <Image file="tile.png" />
+ <Image x="80" width="100" height="100" file="tile.png" />
+ <Image x="190" width="100" height="100" tile="true" file="tile.png" />
+ </Item>
+ \endqml
+ \endqmltext
+
+ \ingroup coreitems
+*/
+
+/*!
+ \fn void QFxItem::activeFocusChanged()
+
+ This signal is emitted when this item gains active focus.
+*/
+
+/*!
+ \fn void QFxItem::baselineChanged()
+
+ This signal is emitted when the baseline of the item changes.
+
+ The baseline may change in response to a call to setBaselineOffset()
+ or due to the geometry of the item changing.
+
+ \sa baselineOffset(), setBaselineOffset()
+*/
+
+/*!
+ \fn void QFxItem::baselineOffsetChanged()
+
+ This signal is emitted when the baseline of the item is changed
+ via setBaselineOffset().
+
+ The baseline corresponds to the baseline of the text contained in
+ the element. It is useful for aligning the text in items placed
+ beside each other. The default baseline is positioned at
+ 2/3 of the height of the item.
+
+ \sa baselineOffset(), setBaselineOffset()
+*/
+
+/*!
+ \fn void QFxItem::leftChanged()
+
+ This signal is emitted when the left coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::rightChanged()
+
+ This signal is emitted when the right coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::topChanged()
+
+ This signal is emitted when the top coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::bottomChanged()
+
+ This signal is emitted when the bottom coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::widthChanged()
+
+ This signal is emitted when the width of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::heightChanged()
+
+ This signal is emitted when the height of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::hcenterChanged()
+
+ This signal is emitted when the horizontal center coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::vcenterChanged()
+
+ This signal is emitted when the vertical center coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::scaleChanged()
+
+ This signal is emitted when the scale of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::stateChanged(const QString &state)
+
+ This signal is emitted when the \a state of the item changes.
+
+ \sa states-transitions
+*/
+
+/*!
+ \fn void QFxItem::keyPress()
+
+ This signal is emitted when a key is pressed.
+
+ The key event is available in QML via the QFxKeyEvent \c event
+ property.
+
+ \qml
+ <Item onKeyPress="if (event.key == Qt.Key_Enter) state='Enter'"/>
+ \endqml
+
+ \sa keyRelease()
+*/
+
+/*!
+ \fn void QFxItem::keyRelease()
+
+ This signal is emitted when a key is released.
+
+ The key event is available in QML via the QFxKeyEvent \c event
+ property.
+
+ \qml
+ <Item onKeyRelease="if (event.key == Qt.Key_Enter) state='Enter'"/>
+ \endqml
+
+ \sa keyPress()
+*/
+
+/*!
+ \fn void QFxItem::visibleChanged()
+
+ This signal is emitted when the visibility of the item changes.
+
+ \sa setVisible()
+*/
+
+/*!
+ \fn void QFxItem::opacityChanged()
+
+ This signal is emitted when the opacity of the item changes.
+
+ \sa opacity(), setOpacity()
+*/
+
+/*!
+ \fn void QFxItem::parentChanged()
+
+ This signal is emitted when the parent of the item changes.
+
+ \sa setItemParent()
+*/
+
+/*!
+ \fn void QFxItem::focusChanged()
+
+ This signal is emitted when the item's focus state changes.
+
+ \sa setFocus()
+*/
+
+/*!
+ \fn QFxItem::QFxItem(QFxItem *parent)
+
+ Constructs a QFxItem with the given \a parent.
+*/
+QFxItem::QFxItem(QFxItem* parent)
+ : QSimpleCanvasItem(*(new QFxItemPrivate), parent)
+{
+ Q_D(QFxItem);
+ d->init(parent);
+}
+
+/*! \internal
+*/
+QFxItem::QFxItem(QFxItemPrivate &dd, QFxItem *parent)
+ : QSimpleCanvasItem(dd, parent)
+{
+ Q_D(QFxItem);
+ d->init(parent);
+}
+
+/*! \internal
+*/
+void QFxItem::doUpdate()
+{
+ update();
+}
+
+/*!
+ Destroys the QFxItem.
+*/
+QFxItem::~QFxItem()
+{
+ Q_D(QFxItem);
+ delete d->_anchorLines; d->_anchorLines = 0;
+}
+
+/*!
+ \qmlproperty enum Item::transformOrigin
+ This property holds the origin point around which scale and rotation transform.
+
+ Nine transform origins are available, as shown in the image below.
+
+ \image declarative-transformorigin.png
+
+ This example scales an image about its center.
+ \code
+ <Image src="myimage.png" transformOrigin="Center" scale="4" />
+ \endcode
+
+ The default transform origin is \c TopLeft.
+*/
+/*!
+ \qmlproperty Item Item::parent
+ This property holds the parent of the item.
+*/
+void QFxItem::setItemParent(QFxItem *parent)
+{
+ setParent(parent);
+}
+
+/*!
+ XXX Playing around with view2view transitions.
+ */
+void QFxItem::moveToParent(QFxItem *parent)
+{
+ if(parent && itemParent()) {
+ QPointF me = itemParent()->mapToScene(QPointF(0,0));
+ QPointF them = parent->mapToScene(QPointF(0,0));
+
+ QPointF themx = parent->mapToScene(QPointF(1,0));
+ QPointF themy = parent->mapToScene(QPointF(0,1));
+
+ themx -= them;
+ themy -= them;
+
+ setItemParent(parent);
+
+ // XXX - this is silly and will only work in a few cases
+
+ /*
+ xDiff = rx * themx_x + ry * themy_x
+ yDiff = rx * themx_y + ry * themy_y
+ */
+
+ qreal rx = 0;
+ qreal ry = 0;
+ qreal xDiff = them.x() - me.x();
+ qreal yDiff = them.y() - me.y();
+
+
+ if(themx.x() == 0.) {
+ ry = xDiff / themy.x();
+ rx = (yDiff - ry * themy.y()) / themx.y();
+ } else if(themy.x() == 0.) {
+ rx = xDiff / themx.x();
+ ry = (yDiff - rx * themx.y()) / themy.y();
+ } else if(themx.y() == 0.) {
+ ry = yDiff / themy.y();
+ rx = (xDiff - ry * themy.x()) / themx.x();
+ } else if(themy.y() == 0.) {
+ rx = yDiff / themx.y();
+ ry = (xDiff - rx * themx.x()) / themy.x();
+ } else {
+ qreal div = (themy.x() * themx.y() - themy.y() * themx.x());
+
+ if(div != 0.)
+ rx = (themx.y() * xDiff - themx.x() * yDiff) / div;
+
+ if(themy.y() != 0.) ry = (yDiff - rx * themx.y()) / themy.y();
+ }
+
+ setX(x() - rx);
+ setY(y() - ry);
+ } else {
+ setItemParent(parent);
+ }
+}
+
+/*!
+ Returns the QFxItem parent of this item.
+*/
+QFxItem *QFxItem::itemParent() const
+{
+ return qobject_cast<QFxItem *>(QObject::parent());
+}
+
+/*!
+ \qmlproperty list<Item> Item::children
+ \qmlproperty list<Object> Item::resources
+
+ The children property contains the list of visual children of this element.
+ The resources property contains non-visual resources that you want to
+ reference by name.
+
+ Generally you can rely on Item's default property to handle all this for
+ you, but it can come in handy in some cases.
+
+ \qml
+ <Item>
+ <children>
+ <Text />
+ <Rect />
+ </children>
+ <resources>
+ <Component id="myComponent">
+ <Text />
+ </Component>
+ </resources>
+ </Item>
+ \endqml
+*/
+
+/*!
+ Returns true if all of the attributes set via QML have been set;
+ otherwise returns false.
+
+ \sa classComplete()
+*/
+bool QFxItem::isClassComplete() const
+{
+ Q_D(const QFxItem);
+ return d->_classComplete;
+}
+
+/*!
+ Returns true if construction of the QML component is complete; otherwise
+ returns false.
+
+ It is often desireable to delay some processing until the component is
+ completed.
+
+ \sa componentComplete().
+*/
+bool QFxItem::isComponentComplete() const
+{
+ Q_D(const QFxItem);
+ return d->_componentComplete;
+}
+
+/*!
+ \property QFxItem::anchors
+ \brief The anchors (alignments) used by the item.
+*/
+QFxAnchors *QFxItem::anchors()
+{
+ Q_D(QFxItem);
+ return d->anchors();
+}
+
+void QFxItemPrivate::data_removeAt(int)
+{
+ // ###
+}
+
+int QFxItemPrivate::data_count() const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::data_append(QObject *o)
+{
+ Q_Q(QFxItem);
+ QFxItem *i = qobject_cast<QFxItem *>(o);
+ if(i)
+ q->children()->append(i);
+ else
+ resources_append(o);
+}
+
+void QFxItemPrivate::data_insert(int, QObject *)
+{
+ // ###
+}
+
+QObject *QFxItemPrivate::data_at(int) const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::data_clear()
+{
+ // ###
+}
+
+void QFxItemPrivate::resources_removeAt(int)
+{
+ // ###
+}
+
+int QFxItemPrivate::resources_count() const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::resources_append(QObject *o)
+{
+ Q_Q(QFxItem);
+ o->setParent(q);
+}
+
+void QFxItemPrivate::resources_insert(int, QObject *)
+{
+ // ###
+}
+
+QObject *QFxItemPrivate::resources_at(int) const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::resources_clear()
+{
+ // ###
+}
+
+void QFxItemPrivate::children_removeAt(int)
+{
+ // ###
+}
+
+int QFxItemPrivate::children_count() const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::children_append(QFxItem *i)
+{
+ Q_Q(QFxItem);
+ i->setParent(q);
+}
+
+void QFxItemPrivate::children_insert(int, QFxItem *)
+{
+ // ###
+}
+
+QFxItem *QFxItemPrivate::children_at(int) const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::children_clear()
+{
+ // ###
+}
+
+/*!
+ \qmlproperty list<Object> Item::data
+ \default
+
+ The data property is allows you to freely mix visual children and resources
+ of an element. If you assign a visual element to the data list it becomes
+ a child and if you assign any other object type, it is added as a resource.
+
+ So you can write:
+ \qml
+ <Item>
+ <Text />
+ <Rect />
+ <Script />
+ </Item>
+ \endqml
+
+ instead of:
+ \qml
+ <Item>
+ <children>
+ <Text />
+ <Rect />
+ </children>
+ <resources>
+ <Script/>
+ </resources>
+ </Item>
+ \endqml
+
+ data is a behind-the-scenes property: you should never need to explicitly
+ specify it.
+ */
+QmlList<QObject *> *QFxItem::data()
+{
+ Q_D(QFxItem);
+ return &d->data;
+}
+
+/*!
+ \property QFxItem::contents
+ \brief An object that knows about the size of an item's children.
+
+ contents provides an easy way to access the (collective) width and
+ height of the item's children.
+*/
+QFxContents *QFxItem::contents()
+{
+ Q_D(QFxItem);
+ if (!d->_contents) {
+ d->_contents = new QFxContents;
+ d->_contents->setParent(this);
+ d->_contents->setItem(this);
+ }
+ return d->_contents;
+}
+
+QFxItem *QFxItem::qmlItem() const
+{
+ Q_D(const QFxItem);
+ return d->qmlItem;
+}
+
+/*!
+ \qmlproperty string Item::qml
+ This property holds the dynamic QML for the item.
+
+ This property is used for dynamically loading QML into the
+ item. Querying for the QML only has meaning if the QML has been
+ dynamically set; otherwise an empty string is returned.
+*/
+QString QFxItem::qml() const
+{
+ Q_D(const QFxItem);
+ return d->_qml;
+}
+
+void QFxItem::setQml(const QString &qml)
+{
+ Q_D(QFxItem);
+ if (d->_qml == qml)
+ return;
+
+ if(!d->_qml.isEmpty()) {
+ QmlChildren::Iterator iter = d->_qmlChildren.find(d->_qml);
+ if(iter != d->_qmlChildren.end())
+ (*iter)->setOpacity(0.);
+ }
+
+ d->_qml = qml;
+ d->_qmlurl = itemContext()->resolvedUri(qml);
+ d->qmlItem = 0;
+
+ if(d->_qml.isEmpty()) {
+ emit qmlChanged();
+ return;
+ }
+
+ QmlChildren::Iterator iter = d->_qmlChildren.find(d->_qml);
+ if(iter != d->_qmlChildren.end()) {
+ (*iter)->setOpacity(1.);
+ d->qmlItem = (*iter);
+ emit qmlChanged();
+ } else {
+ d->_qmlcomp =
+ new QmlComponent(itemContext()->engine(), d->_qmlurl, this);
+ if(d->_qmlcomp->isReady())
+ qmlLoaded();
+ else
+ QObject::connect(d->_qmlcomp, SIGNAL(readyChanged()),
+ this, SLOT(qmlLoaded()));
+ }
+}
+
+
+void QFxItem::qmlLoaded()
+{
+ Q_D(QFxItem);
+
+ { // newChild...
+ // ###
+ for (int i=0; i<d->_qmlnewloading.length(); ++i) {
+ QmlComponent *c = d->_qmlnewcomp.at(i);
+ if(!c->isReady())
+ continue;
+
+ QmlContext *ctxt = new QmlContext(itemContext());
+ QObject* o = c ? c->create(ctxt):0;
+ QFxItem* ret = qobject_cast<QFxItem*>(o);
+ if (ret) {
+ ret->setItemParent(this);
+ QScriptValue v = itemContext()->engine()->scriptEngine()->newQObject(ret);
+ emit newChildCreated(d->_qmlnewloading.at(i).toString(),v);
+ }
+
+ delete c;
+ d->_qmlnewloading.removeAt(i);
+ d->_qmlnewcomp.removeAt(i);
+ --i;
+ }
+ }
+
+ // setQml...
+ if (d->_qmlcomp) {
+ QmlContext *ctxt = new QmlContext(itemContext());
+ ctxt->addDefaultObject(this);
+
+ QObject *obj = d->_qmlcomp->create(ctxt);
+ QFxItem *qmlChild = qobject_cast<QFxItem *>(obj);
+ if(qmlChild) {
+ qmlChild->setItemParent(this);
+ d->_qmlChildren.insert(d->_qml, qmlChild);
+ d->qmlItem = qmlChild;
+ } else {
+ delete qmlChild;
+ d->_qml = QString();
+ }
+ delete d->_qmlcomp;
+ d->_qmlcomp = 0;
+ emit qmlChanged();
+ }
+}
+
+/*!
+ \qmlproperty Item Item::clipToItem
+
+ Experimental clip to item support. Do not use.
+
+ \todo complete clip to item support.
+ */
+QFxItem *QFxItem::clipToItem() const
+{
+ return 0;
+}
+
+void QFxItem::setClipToItem(QFxItem *)
+{
+ qWarning() << "QFxItem: clipToItem not implemented";
+}
+
+/*!
+ \qmlproperty real Item::x
+ \qmlproperty real Item::y
+ \qmlproperty int Item::width
+ \qmlproperty int Item::height
+
+ Defines the item's position and size relative to its parent.
+
+ \qml
+ <Item x="100" y="100" width="100" height="100" />
+ \endqml
+ */
+
+/*!
+ \qmlproperty real Item::z
+
+ Sets the stacking order of the item. By default the stacking order is 0.
+
+ Items with a higher stacking value are drawn on top of items with a
+ lower stacking order. Items with the same stacking value are drawn
+ bottom up in the order they appear. Items with a negative stacking
+ value are drawn under their parent's content.
+
+ The following example shows the various effects of stacking order.
+
+ \table
+ \row
+ \o \image declarative-item_stacking1.png
+ \o Same \c z - later children above earlier children:
+ \qml
+ <Item>
+ <Rect color="red" width="100" height="100" />
+ <Rect color="blue" x="50" y="50" width="100" height="100" />
+ </Item>
+ \endqml
+ \row
+ \o \image declarative-item_stacking2.png
+ \o Higher \c z on top:
+ \qml
+ <Item>
+ <Rect z="1" color="red" width="100" height="100" />
+ <Rect color="blue" x="50" y="50" width="100" height="100" />
+ </Item>
+ \endqml
+ \row
+ \o \image declarative-item_stacking3.png
+ \o Same \c z - children above parents:
+ \qml
+ <Item>
+ <Rect color="red" width="100" height="100">
+ <Rect color="blue" x="50" y="50" width="100" height="100" />
+ </Rect>
+ </Item>
+ \endqml
+ \row
+ \o \image declarative-item_stacking4.png
+ \o Lower \c z below:
+ \qml
+ <Item>
+ <Rect color="red" width="100" height="100">
+ <Rect z="-1" color="blue" x="50" y="50" width="100" height="100" />
+ </Rect>
+ </Item>
+ \endqml
+ \endtable
+ */
+/*!
+ \property QFxItem::z
+ \brief The z coordinate of the item relative to its parent.
+
+ A negative z coordinate means the item will be painted below its parent.
+*/
+
+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(newGeometry.x() != oldGeometry.x()) {
+ emit leftChanged();
+ emit hcenterChanged();
+ emit rightChanged();
+ }
+
+ 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();
+}
+
+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();
+ }
+ }
+ 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();
+}
+
+/*!
+ \qmlproperty bool Item::flipVertically
+ \qmlproperty bool Item::flipHorizontally
+
+ When set, the item will be displayed flipped horizontally or vertically
+ about its center.
+ */
+bool QFxItem::flipVertically() const
+{
+ return flip() & VerticalFlip;
+}
+
+void QFxItem::setFlipVertically(bool v)
+{
+ if(v)
+ setFlip((QSimpleCanvasItem::Flip)(flip() | VerticalFlip));
+ else
+ setFlip((QSimpleCanvasItem::Flip)(flip() & ~VerticalFlip));
+}
+
+bool QFxItem::flipHorizontally() const
+{
+ return flip() & HorizontalFlip;
+}
+
+void QFxItem::setFlipHorizontally(bool v)
+{
+ if(v)
+ setFlip((QSimpleCanvasItem::Flip)(flip() | HorizontalFlip));
+ else
+ setFlip((QSimpleCanvasItem::Flip)(flip() & ~HorizontalFlip));
+}
+
+class QFxKeyEvent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int key READ key);
+ Q_PROPERTY(QString text READ text);
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted);
+public:
+ QFxKeyEvent(int key, const QString &text=QString()) : _accepted(false), _key(key), _text(text) {}
+
+ bool isAccepted() { return _accepted; }
+ void setAccepted(bool accepted) { _accepted = accepted; }
+
+ int key() const { return _key; }
+
+ QString text() const { return _text; }
+
+private:
+ bool _accepted;
+ int _key;
+ QString _text;
+};
+
+/*!
+ \reimp
+*/
+void QFxItem::keyPressEvent(QKeyEvent *event)
+{
+ QFxKeyEvent ke(event->key(), event->text());
+ emit keyPress(&ke);
+ event->setAccepted(ke.isAccepted());
+ if (itemParent() && !ke.isAccepted())
+ itemParent()->keyPressEvent(event);
+}
+
+/*!
+ \reimp
+*/
+void QFxItem::keyReleaseEvent(QKeyEvent *event)
+{
+ QFxKeyEvent ke(event->key(), event->text());
+ emit keyRelease(&ke);
+ event->setAccepted(ke.isAccepted());
+ if (itemParent() && !ke.isAccepted())
+ itemParent()->keyReleaseEvent(event);
+}
+
+/*!
+ Returns the bounding rectangle of the item in scene coordinates.
+*/
+QRectF QFxItem::sceneBoundingRect() const
+{
+ return QRectF(mapToScene(QPointF(0,0)), QSize(width(), height()));
+}
+
+/*!
+ \qmlproperty string Item::id
+ This property holds the identifier for the item.
+
+ The identifier can be used in bindings and other expressions to
+ refer to the item. For example:
+
+ \qml
+ <Text id="myText" .../>
+ <Text text="{myText.text}"/>
+ \endqml
+
+ The identifier is available throughout to the \l {components}{component}
+ where it is declared. Two items in the same component
+ with the same identifier is invalid.
+*/
+QString QFxItem::id() const
+{
+ Q_D(const QFxItem);
+ return d->_id;
+}
+
+void QFxItem::setId(const QString &id)
+{
+ Q_D(QFxItem);
+ setObjectName(id);
+ d->_id = id;
+}
+
+QFxAnchorLine QFxItem::left() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->left;
+}
+
+QFxAnchorLine QFxItem::right() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->right;
+}
+
+QFxAnchorLine QFxItem::horizontalCenter() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->hCenter;
+}
+
+QFxAnchorLine QFxItem::top() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->top;
+}
+
+QFxAnchorLine QFxItem::bottom() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->bottom;
+}
+
+QFxAnchorLine QFxItem::verticalCenter() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->vCenter;
+}
+
+/*!
+ \qmlproperty AnchorLine Item::top
+ \qmlproperty AnchorLine Item::bottom
+ \qmlproperty AnchorLine Item::left
+ \qmlproperty AnchorLine Item::right
+ \qmlproperty AnchorLine Item::horizontalCenter
+ \qmlproperty AnchorLine Item::verticalCenter
+
+ The anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \qmlproperty AnchorLine Item::anchors.top
+ \qmlproperty AnchorLine Item::anchors.bottom
+ \qmlproperty AnchorLine Item::anchors.left
+ \qmlproperty AnchorLine Item::anchors.right
+ \qmlproperty AnchorLine Item::anchors.horizontalCenter
+ \qmlproperty AnchorLine Item::anchors.verticalCenter
+
+ \qmlproperty Item Item::anchors.fill
+
+ \qmlproperty int Item::anchors.topMargin
+ \qmlproperty int Item::anchors.bottomMargin
+ \qmlproperty int Item::anchors.leftMargin
+ \qmlproperty int Item::anchors.rightMargin
+ \qmlproperty int Item::anchors.horizontalCenterOffset
+ \qmlproperty int Item::anchors.verticalCenterOffset
+
+ Anchors provide a way to position an item by specifying its
+ relationship with other items.
+
+ Margins apply to top, bottom, left, right, and fill anchors.
+
+ Offsets apply for horizontal and vertical center anchors.
+
+ \table
+ \row
+ \o \image declarative-anchors_example.png
+ \o Text anchored to Image, horizontally centered and vertically below, with a margin.
+ \qml
+ <Image id="pic" .../>
+ <Text id="label" anchors.horizontalCenter="{pic.horizontalCenter}"
+ anchors.top="{pic.bottom}"
+ anchors.topMargin="5" .../>
+ \endqml
+ \row
+ \o \image declarative-anchors_example2.png
+ \o
+ Left of Text anchored to right of Image, with a margin. The y
+ property of both defaults to 0.
+
+ \qml
+ <Image id="pic" .../>
+ <Text id="label" anchors.left="{pic.right}"
+ anchors.leftMargin="5" .../>
+ \endqml
+ \endtable
+
+ anchors.fill provides a convenient way for one item to have the
+ same geometry as another item, and is equivalent to connecting all
+ four directional anchors.
+
+ \note You can only anchor an item to siblings or a parent.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*
+ \property QFxItem::baseline
+ \brief The position of the item's baseline in global (scene) coordinates.
+
+ 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 QFxItem::baselineOffset() const
+{
+ Q_D(const QFxItem);
+ if (!d->_baselineOffset.isValid()) {
+ return height()*2/3; //### default baseline is 2/3 of the way to the bottom of the item
+ } else
+ return d->_baselineOffset;
+}
+
+void QFxItem::setBaselineOffset(int offset)
+{
+ Q_D(QFxItem);
+ if (offset == d->_baselineOffset)
+ return;
+
+ d->_baselineOffset = offset;
+ emit baselineOffsetChanged();
+ emit baselineChanged();
+}
+
+/*!
+ \qmlproperty real Item::rotation
+ This property holds the rotation of the item in degrees.
+
+ This specifies how many degrees to rotate the item around its origin (0,0).
+ The default rotation is 0 degrees (i.e. not rotated at all).
+
+ \table
+ \row
+ \o \image declarative-rotation.png
+ \o
+ \qml
+ <Rect color="blue" width="100" height="100">
+ <Rect color="green" width="25" height="25"/>
+ <Rect color="red" width="50" height="50" x="25" y="25" rotation="30"/>
+ </Rect>
+ \endqml
+ \endtable
+*/
+qreal QFxItem::rotation() const
+{
+ Q_D(const QFxItem);
+ return d->_rotation;
+}
+
+void QFxItem::setRotation(qreal rotation)
+{
+ Q_D(QFxItem);
+ if (d->_rotation == rotation)
+ return;
+ d->_rotation = rotation;
+#if defined(QFX_RENDER_OPENGL)
+ QMatrix4x4 trans;
+ QPointF to = transformOriginPoint();
+ trans.translate(to.x(), to.y());
+ trans.rotate(d->_rotation, 0, 0, 1);
+ trans.translate(-to.x(), -to.y());
+#else
+ QTransform trans;
+ QPointF to = transformOriginPoint();
+ trans.translate(to.x(), to.y());
+ trans.rotate(d->_rotation);
+ trans.translate(-to.x(), -to.y());
+#endif
+ setTransform(trans);
+ emit rotationChanged();
+}
+
+/*!
+ \qmlproperty real Item::scale
+ This property holds the scale of the item.
+
+ A scale of less than 1 means the item will be displayed smaller than
+ normal, and a scale of greater than 1 means the item will be
+ displayed larger than normal. A negative scale means the item will
+ be mirrored.
+
+ By default, items are displayed at a scale of 1 (i.e. at their
+ normal size).
+
+ Scaling is from the item's origin (0,0).
+
+ \table
+ \row
+ \o \image declarative-scale.png
+ \o
+ \qml
+ <Rect color="blue" width="100" height="100">
+ <Rect color="green" width="25" height="25"/>
+ <Rect color="red" width="50" height="50" x="25" y="25" scale="1.4"/>
+ </Rect>
+ \endqml
+ \endtable
+*/
+qreal QFxItem::scale() const
+{
+ return QSimpleCanvasItem::scale();
+}
+
+void QFxItem::setScale(qreal s)
+{
+ if (QSimpleCanvasItem::scale() == s) return;
+ QSimpleCanvasItem::setScale(s);
+ emit scaleChanged();
+ update();
+}
+
+/*!
+ \qmlproperty real Item::opacity
+
+ The opacity of the item. Opacity is specified as a number between 0
+ (fully transparent) and 1 (fully opaque). The default is 1.
+
+ Opacity is an \e inherited attribute. That is, the opacity is
+ also applied individually to child items. In almost all cases this
+ is what you want. If you can spot the issue in the following
+ example, you might need to use an opacity filter instead.
+
+ \table
+ \row
+ \o \image declarative-item_opacity1.png
+ \o
+ \qml
+ <Item>
+ <Rect color="red" width="100" height="100">
+ <Rect color="blue" x="50" y="50" width="100" height="100" />
+ </Rect>
+ </Item>
+ \endqml
+ \row
+ \o \image declarative-item_opacity2.png
+ \o
+ \qml
+ <Item>
+ <Rect opacity="0.5" color="red" width="100" height="100">
+ <Rect color="blue" x="50" y="50" width="100" height="100" />
+ </Rect>
+ </Item>
+ \endqml
+ \endtable
+
+ \todo There is no such thing as an opacity filter
+*/
+
+qreal QFxItem::opacity() const
+{
+ return QSimpleCanvasItem::visible();
+}
+
+void QFxItem::setOpacity(qreal v)
+{
+ if(v == QSimpleCanvasItem::visible())
+ return;
+
+ if(v < 0) v = 0;
+ else if(v > 1) v = 1;
+ QSimpleCanvasItem::setVisible(v);
+
+ emit opacityChanged();
+}
+
+bool QFxItem::keepMouseGrab() const
+{
+ Q_D(const QFxItem);
+ return d->_keepMouse;
+}
+
+void QFxItem::setKeepMouseGrab(bool keep)
+{
+ Q_D(QFxItem);
+ d->_keepMouse = keep;
+}
+
+void QFxItem::activeFocusChanged(bool)
+{
+ emit activeFocusChanged();
+}
+
+void QFxItem::focusChanged(bool)
+{
+ emit focusChanged();
+}
+
+QmlList<QFxItem *> *QFxItem::children()
+{
+ Q_D(QFxItem);
+ return &(d->children);
+}
+
+QmlList<QObject *> *QFxItem::resources()
+{
+ Q_D(QFxItem);
+ return &(d->resources);
+}
+
+/*!
+ \qmlproperty list<State> Item::states
+ This property holds a list of states defined by the item.
+
+ \qml
+ <Item>
+ <states>
+ <State .../>
+ <State .../>
+ ...
+ </states>
+ </Item>
+ \endqml
+
+ \sa {states-transitions}{States and Transitions}
+*/
+QmlList<QmlState *>* QFxItem::states()
+{
+ Q_D(QFxItem);
+ return d->states()->statesProperty();
+}
+
+/*!
+ \qmlproperty list<Transition> Item::transitions
+ This property holds a list of transitions defined by the item.
+
+ \qml
+ <Item>
+ <transitions>
+ <Transition .../>
+ <Transition .../>
+ ...
+ </transitions>
+ </Item>
+ \endqml
+
+ \sa {states-transitions}{States and Transitions}
+*/
+QmlList<QmlTransition *>* QFxItem::transitions()
+{
+ Q_D(QFxItem);
+ return d->states()->transitionsProperty();
+}
+
+/*!
+ \qmlproperty list<Filter> Item::filter
+ This property holds a list of graphical filters to be applied to the item.
+
+ \l {qmlfilter}{Filters} include things like \l {qmlblur}{blurring}
+ the item, or giving it a Reflection. Some
+ filters may not be available on all canvases; if a filter is not
+ available on a certain canvas, it will simply not be applied for
+ that canvas (but the XML will still be considered valid).
+
+ \qml
+ <Item>
+ <filter>
+ <Blur .../>
+ <Relection .../>
+ ...
+ </filter>
+ </Item>
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool Item::clip
+ This property holds whether clipping is enabled.
+
+ if clipping is enabled, an item will clip its own painting, as well
+ as the painting of its children, to its bounding rectangle.
+
+ Non-rectangular clipping regions are not supported for performance reasons.
+*/
+
+/*!
+ Returns the state with \a name. Returns 0 if no matching state is found.
+*/
+QmlState *QFxItem::findState(const QString &name) const
+{
+ Q_D(const QFxItem);
+ if(!d->_stateGroup)
+ return 0;
+ else
+ return d->_stateGroup->findState(name);
+}
+
+/*!
+ \qmlproperty string Item::state
+
+ This property holds the name of the current state of the item.
+
+ This property is often used in scripts to change between states. For
+ example:
+
+ \qml
+ <Script>
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
+ }
+ </Script>
+ \endqml
+
+ If the item is in its base state (i.e. no explicit state has been
+ set), \c state will be a blank string. Likewise, you can return an
+ item to its base state by setting its current state to \c ''.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+QString QFxItem::state() const
+{
+ Q_D(const QFxItem);
+ if(!d->_stateGroup)
+ return QString();
+ else
+ return d->_stateGroup->state();
+}
+
+void QFxItem::setState(const QString &state)
+{
+ Q_D(QFxItem);
+ d->states()->setState(state);
+}
+
+/*!
+ \qmlproperty list<Transform> Item::transform
+ This property holds the list of transformations to apply.
+
+ For more information see \l Transform.
+*/
+QList<QFxTransform *> *QFxItem::transform()
+{
+ Q_D(QFxItem);
+ return &(d->_transform);
+}
+
+/*!
+ Returns true if the item is visible; otherwise returns false.
+
+ An item is considered visible if its opacity is not 0.
+*/
+bool QFxItem::isVisible() const
+{
+ Q_D(const QFxItem);
+ return d->visible;
+}
+
+/*!
+ Sets the visibility of the item to \a visible.
+
+ Setting visibility to false sets opacity to 0. Setting the
+ visibility to true restores the opacity to its previous value.
+*/
+void QFxItem::setVisible(bool visible)
+{
+ Q_D(QFxItem);
+ if(visible == d->visible)
+ return;
+
+ d->visible = visible;
+ if(visible)
+ setOpacity(d->visibleOp);
+ else {
+ d->visibleOp = opacity();
+ setOpacity(0);
+ }
+
+ emit visibleChanged();
+}
+
+/*! \internal
+*/
+void QFxItem::dump(int depth)
+{
+ Q_D(QFxItem);
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << metaObject()->className() << "(" << (void *)static_cast<QFxItem*>(this) << ", " << (void *)static_cast<QSimpleCanvasItem*>(this) << "):" << x() << y() << width() << height() << (void *) itemParent();
+}
+
+/*! \internal
+*/
+QString QFxItem::propertyInfo() const
+{
+ return QString();
+}
+
+/*!
+ Creates a new child of the given component \a type. The
+ newChildCreated() signal will be emitted when and if the child is
+ successfully created.
+
+ \preliminary
+*/
+void QFxItem::newChild(const QString &type)
+{
+ Q_D(QFxItem);
+
+ QUrl url = itemContext()->resolvedUri(type);
+ if (url.isEmpty())
+ return;
+
+ d->_qmlnewloading.append(url);
+ d->_qmlnewcomp.append(new QmlComponent(itemContext()->engine(), url, this));
+
+ if(d->_qmlnewcomp.last()->isReady())
+ qmlLoaded();
+ else
+ connect(d->_qmlnewcomp.last(), SIGNAL(readyChanged()),
+ this, SLOT(qmlLoaded()));
+}
+
+/*!
+ classBegin() is called when the item is constructed, but its
+ properties have not yet been set.
+
+ \sa classComplete(), componentComplete(), isClassComplete(), isComponentComplete()
+*/
+void QFxItem::classBegin()
+{
+ Q_D(QFxItem);
+ d->_classComplete = false;
+ d->_componentComplete = false;
+ if(d->_stateGroup)
+ d->_stateGroup->classBegin();
+}
+
+/*!
+ classComplete() is called when all properties specified in QML
+ have been assigned. It is sometimes desireable to delay some
+ processing until all property assignments are complete.
+*/
+void QFxItem::classComplete()
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ItemClassComplete> cc;
+#endif
+ Q_D(QFxItem);
+ d->_classComplete = true;
+ if(d->_stateGroup)
+ d->_stateGroup->classComplete();
+}
+
+/*!
+ componentComplete() is called when all elements in the component
+ have been constructed. It is often desireable to delay some
+ processing until the component is complete an all bindings in the
+ component have been resolved.
+*/
+void QFxItem::componentComplete()
+{
+ Q_D(QFxItem);
+ d->_componentComplete = true;
+ if(d->_stateGroup)
+ d->_stateGroup->componentComplete();
+ if(d->_anchors) {
+ d->anchors()->connectHAnchors();
+ d->anchors()->connectVAnchors();
+ }
+ if(!d->_transform.isEmpty())
+ updateTransform();
+}
+
+/*! \internal
+*/
+void QFxItem::parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *)
+{
+ emit parentChanged();
+}
+
+/*! \internal
+*/
+void QFxItem::reparentItems()
+{
+ qFatal("EEK");
+}
+
+void QFxItem::updateTransform()
+{
+ Q_D(QFxItem);
+ QSimpleCanvas::Matrix trans;
+ for(int ii = d->_transform.count() - 1; ii >= 0; --ii) {
+ QFxTransform *a = d->_transform.at(ii);
+ if(!a->isIdentity())
+ trans = a->transform() * trans;
+ }
+
+ setTransform(trans);
+ transformChanged(trans);
+}
+
+void QFxItem::transformChanged(const QSimpleCanvas::Matrix &)
+{
+}
+
+/*!
+ Returns the current QML context for this item.
+*/
+QmlContext *QFxItem::itemContext() const
+{
+ Q_D(const QFxItem);
+ return d->_ctxt;
+}
+
+QmlStateGroup *QFxItemPrivate::states()
+{
+ Q_Q(QFxItem);
+ if(!_stateGroup) {
+ _stateGroup = new QmlStateGroup(q);
+ if(!_classComplete)
+ _stateGroup->classBegin();
+ QObject::connect(_stateGroup, SIGNAL(stateChanged(QString)),
+ q, SIGNAL(stateChanged(QString)));
+ }
+
+ return _stateGroup;
+}
+
+QFxItemPrivate::AnchorLines::AnchorLines(QFxItem *q)
+{
+ left.item = q;
+ left.anchorLine = QFxAnchorLine::Left;
+ right.item = q;
+ right.anchorLine = QFxAnchorLine::Right;
+ hCenter.item = q;
+ hCenter.anchorLine = QFxAnchorLine::HCenter;
+ top.item = q;
+ top.anchorLine = QFxAnchorLine::Top;
+ bottom.item = q;
+ bottom.anchorLine = QFxAnchorLine::Bottom;
+ vCenter.item = q;
+ vCenter.anchorLine = QFxAnchorLine::VCenter;
+}
+
+#include "qfxitem.moc"
+QT_END_NAMESPACE