src/declarative/graphicsitems/qdeclarativeflipable.cpp
changeset 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "private/qdeclarativeflipable_p.h"
       
    43 
       
    44 #include "private/qdeclarativeitem_p.h"
       
    45 #include "private/qdeclarativeguard_p.h"
       
    46 
       
    47 #include <qdeclarativeinfo.h>
       
    48 
       
    49 #include <QtGui/qgraphicstransform.h>
       
    50 
       
    51 QT_BEGIN_NAMESPACE
       
    52 
       
    53 class QDeclarativeFlipablePrivate : public QDeclarativeItemPrivate
       
    54 {
       
    55     Q_DECLARE_PUBLIC(QDeclarativeFlipable)
       
    56 public:
       
    57     QDeclarativeFlipablePrivate() : current(QDeclarativeFlipable::Front), front(0), back(0) {}
       
    58 
       
    59     void updateSceneTransformFromParent();
       
    60     void setBackTransform();
       
    61 
       
    62     QDeclarativeFlipable::Side current;
       
    63     QDeclarativeGuard<QGraphicsObject> front;
       
    64     QDeclarativeGuard<QGraphicsObject> back;
       
    65 
       
    66     bool wantBackXFlipped;
       
    67     bool wantBackYFlipped;
       
    68 };
       
    69 
       
    70 /*!
       
    71     \qmlclass Flipable QDeclarativeFlipable
       
    72     \since 4.7
       
    73     \brief The Flipable item provides a surface that can be flipped.
       
    74     \inherits Item
       
    75 
       
    76     Flipable is an item that can be visibly "flipped" between its front and
       
    77     back sides. It is used together with Rotation and State/Transition to
       
    78     produce a flipping effect.
       
    79 
       
    80     Here is a Flipable that flips whenever it is clicked:
       
    81 
       
    82     \snippet doc/src/snippets/declarative/flipable.qml 0
       
    83 
       
    84     \image flipable.gif
       
    85 
       
    86     The Rotation element is used to specify the angle and axis of the flip,
       
    87     and the State defines the changes in angle which produce the flipping
       
    88     effect. Finally, the Transition creates the animation that changes the
       
    89     angle over one second.
       
    90 */
       
    91 
       
    92 /*!
       
    93     \internal
       
    94     \class QDeclarativeFlipable
       
    95     \brief The Flipable item provides a surface that can be flipped.
       
    96 
       
    97     Flipable is an item that can be visibly "flipped" between its front and
       
    98     back sides.
       
    99 */
       
   100 
       
   101 QDeclarativeFlipable::QDeclarativeFlipable(QDeclarativeItem *parent)
       
   102 : QDeclarativeItem(*(new QDeclarativeFlipablePrivate), parent)
       
   103 {
       
   104 }
       
   105 
       
   106 QDeclarativeFlipable::~QDeclarativeFlipable()
       
   107 {
       
   108 }
       
   109 
       
   110 /*!
       
   111   \qmlproperty Item Flipable::front
       
   112   \qmlproperty Item Flipable::back
       
   113 
       
   114   The front and back sides of the flipable.
       
   115 */
       
   116 
       
   117 QGraphicsObject *QDeclarativeFlipable::front()
       
   118 {
       
   119     Q_D(const QDeclarativeFlipable);
       
   120     return d->front;
       
   121 }
       
   122 
       
   123 void QDeclarativeFlipable::setFront(QGraphicsObject *front)
       
   124 {
       
   125     Q_D(QDeclarativeFlipable);
       
   126     if (d->front) {
       
   127         qmlInfo(this) << tr("front is a write-once property");
       
   128         return;
       
   129     }
       
   130     d->front = front;
       
   131     d->front->setParentItem(this);
       
   132     if (Back == d->current)
       
   133         d->front->setOpacity(0.);
       
   134 }
       
   135 
       
   136 QGraphicsObject *QDeclarativeFlipable::back()
       
   137 {
       
   138     Q_D(const QDeclarativeFlipable);
       
   139     return d->back;
       
   140 }
       
   141 
       
   142 void QDeclarativeFlipable::setBack(QGraphicsObject *back)
       
   143 {
       
   144     Q_D(QDeclarativeFlipable);
       
   145     if (d->back) {
       
   146         qmlInfo(this) << tr("back is a write-once property");
       
   147         return;
       
   148     }
       
   149     d->back = back;
       
   150     d->back->setParentItem(this);
       
   151     if (Front == d->current)
       
   152         d->back->setOpacity(0.);
       
   153     connect(back, SIGNAL(widthChanged()),
       
   154             this, SLOT(retransformBack()));
       
   155     connect(back, SIGNAL(heightChanged()),
       
   156             this, SLOT(retransformBack()));
       
   157 }
       
   158 
       
   159 void QDeclarativeFlipable::retransformBack()
       
   160 {
       
   161     Q_D(QDeclarativeFlipable);
       
   162     if (d->current == QDeclarativeFlipable::Back && d->back)
       
   163         d->setBackTransform();
       
   164 }
       
   165 
       
   166 /*!
       
   167   \qmlproperty enumeration Flipable::side
       
   168 
       
   169   The side of the Flippable currently visible. Possible values are \c
       
   170   Flippable.Front and \c Flippable.Back.
       
   171 */
       
   172 QDeclarativeFlipable::Side QDeclarativeFlipable::side() const
       
   173 {
       
   174     Q_D(const QDeclarativeFlipable);
       
   175     if (d->dirtySceneTransform)
       
   176         const_cast<QDeclarativeFlipablePrivate *>(d)->ensureSceneTransform();
       
   177 
       
   178     return d->current;
       
   179 }
       
   180 
       
   181 // determination on the currently visible side of the flipable
       
   182 // has to be done on the complete scene transform to give
       
   183 // correct results.
       
   184 void QDeclarativeFlipablePrivate::updateSceneTransformFromParent()
       
   185 {
       
   186     Q_Q(QDeclarativeFlipable);
       
   187 
       
   188     QDeclarativeItemPrivate::updateSceneTransformFromParent();
       
   189     QPointF p1(0, 0);
       
   190     QPointF p2(1, 0);
       
   191     QPointF p3(1, 1);
       
   192 
       
   193     QPointF scenep1 = sceneTransform.map(p1);
       
   194     QPointF scenep2 = sceneTransform.map(p2);
       
   195     QPointF scenep3 = sceneTransform.map(p3);
       
   196     p1 = q->mapToParent(p1);
       
   197     p2 = q->mapToParent(p2);
       
   198     p3 = q->mapToParent(p3);
       
   199 
       
   200     qreal cross = (scenep1.x() - scenep2.x()) * (scenep3.y() - scenep2.y()) -
       
   201                   (scenep1.y() - scenep2.y()) * (scenep3.x() - scenep2.x());
       
   202 
       
   203     wantBackYFlipped = p1.x() >= p2.x();
       
   204     wantBackXFlipped = p2.y() >= p3.y();
       
   205 
       
   206     QDeclarativeFlipable::Side newSide;
       
   207     if (cross > 0) {
       
   208         newSide = QDeclarativeFlipable::Back;
       
   209     } else {
       
   210         newSide = QDeclarativeFlipable::Front;
       
   211     }
       
   212 
       
   213     if (newSide != current) {
       
   214         current = newSide;
       
   215         if (current == QDeclarativeFlipable::Back && back)
       
   216             setBackTransform();
       
   217         if (front)
       
   218             front->setOpacity((current==QDeclarativeFlipable::Front)?1.:0.);
       
   219         if (back)
       
   220             back->setOpacity((current==QDeclarativeFlipable::Back)?1.:0.);
       
   221         emit q->sideChanged();
       
   222     }
       
   223 }
       
   224 
       
   225 /* Depends on the width/height of the back item, and so needs reevaulating
       
   226    if those change.
       
   227 */
       
   228 void QDeclarativeFlipablePrivate::setBackTransform()
       
   229 {
       
   230     QTransform mat;
       
   231     QGraphicsItemPrivate *dBack = QGraphicsItemPrivate::get(back);
       
   232     mat.translate(dBack->width()/2,dBack->height()/2);
       
   233     if (dBack->width() && wantBackYFlipped)
       
   234         mat.rotate(180, Qt::YAxis);
       
   235     if (dBack->height() && wantBackXFlipped)
       
   236         mat.rotate(180, Qt::XAxis);
       
   237     mat.translate(-dBack->width()/2,-dBack->height()/2);
       
   238     back->setTransform(mat);
       
   239 }
       
   240 
       
   241 QT_END_NAMESPACE