1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtQuick module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qquicktranslate_p.h"
41 #include "qquickitem_p.h"
42 
43 QT_BEGIN_NAMESPACE
44 
45 class QQuickTranslatePrivate : public QQuickTransformPrivate
46 {
47 public:
QQuickTranslatePrivate()48     QQuickTranslatePrivate()
49     : x(0), y(0) {}
50 
51     qreal x;
52     qreal y;
53 };
54 
55 
56 /*!
57     \qmltype Translate
58     \instantiates QQuickTranslate
59     \inqmlmodule QtQuick
60     \ingroup qtquick-visual-transforms
61     \brief Provides a way to move an Item without changing its x or y properties.
62 
63     The Translate type provides independent control over position in addition
64     to the Item's x and y properties.
65 
66     The following example moves the Y axis of the \l Rectangle items while
67     still allowing the \l Row to lay the items out as if they had not been
68     transformed:
69 
70     \qml
71     import QtQuick 2.0
72 
73     Row {
74         Rectangle {
75             width: 100; height: 100
76             color: "blue"
77             transform: Translate { y: 20 }
78         }
79         Rectangle {
80             width: 100; height: 100
81             color: "red"
82             transform: Translate { y: -20 }
83         }
84     }
85     \endqml
86 
87     \image translate.png
88 */
QQuickTranslate(QObject * parent)89 QQuickTranslate::QQuickTranslate(QObject *parent)
90 : QQuickTransform(*new QQuickTranslatePrivate, parent)
91 {
92 }
93 
94 
~QQuickTranslate()95 QQuickTranslate::~QQuickTranslate()
96 {
97 }
98 /*!
99     \qmlproperty real QtQuick::Translate::x
100 
101     The translation along the X axis.
102 
103     The default value is 0.0.
104 */
x() const105 qreal QQuickTranslate::x() const
106 {
107     Q_D(const QQuickTranslate);
108     return d->x;
109 }
110 
setX(qreal x)111 void QQuickTranslate::setX(qreal x)
112 {
113     Q_D(QQuickTranslate);
114     if (d->x == x)
115         return;
116     d->x = x;
117     update();
118     emit xChanged();
119 }
120 
121 /*!
122     \qmlproperty real QtQuick::Translate::y
123 
124     The translation along the Y axis.
125 
126     The default value is 0.0.
127 */
y() const128 qreal QQuickTranslate::y() const
129 {
130     Q_D(const QQuickTranslate);
131     return d->y;
132 }
setY(qreal y)133 void QQuickTranslate::setY(qreal y)
134 {
135     Q_D(QQuickTranslate);
136     if (d->y == y)
137         return;
138     d->y = y;
139     update();
140     emit yChanged();
141 }
142 
applyTo(QMatrix4x4 * matrix) const143 void QQuickTranslate::applyTo(QMatrix4x4 *matrix) const
144 {
145     Q_D(const QQuickTranslate);
146     matrix->translate(d->x, d->y, 0);
147 }
148 
149 class QQuickScalePrivate : public QQuickTransformPrivate
150 {
151 public:
QQuickScalePrivate()152     QQuickScalePrivate()
153         : xScale(1), yScale(1), zScale(1) {}
154     QVector3D origin;
155     qreal xScale;
156     qreal yScale;
157     qreal zScale;
158 };
159 
160 /*!
161     \qmltype Scale
162     \instantiates QQuickScale
163     \inqmlmodule QtQuick
164     \ingroup qtquick-visual-transforms
165     \brief Provides a way to scale an Item.
166 
167     The Scale type provides a way to scale an \l Item through a scale-type
168     transform.
169 
170     It allows different scaling values for the x and y axes, and allows the
171     scale to be relative to an arbitrary point. This gives more control over
172     item scaling than the \l{Item::}{scale} property.
173 
174     The following example scales the X axis of the Rectangle, relative to
175     its interior point (25, 25):
176 
177     \qml
178     Rectangle {
179         width: 100; height: 100
180         color: "blue"
181         transform: Scale { origin.x: 25; origin.y: 25; xScale: 3}
182     }
183     \endqml
184 
185     \sa Rotation, Translate
186 */
QQuickScale(QObject * parent)187 QQuickScale::QQuickScale(QObject *parent)
188     : QQuickTransform(*new QQuickScalePrivate, parent)
189 {
190 }
191 
~QQuickScale()192 QQuickScale::~QQuickScale()
193 {
194 }
195 
196 /*!
197     \qmlpropertygroup QtQuick::Scale::origin
198     \qmlproperty real QtQuick::Scale::origin.x
199     \qmlproperty real QtQuick::Scale::origin.y
200 
201     This property holds the point that the item is scaled from (that is,
202     the point that stays fixed relative to the parent as the rest of the
203     item grows).
204 
205     The default value of the origin is (0, 0).
206 */
origin() const207 QVector3D QQuickScale::origin() const
208 {
209     Q_D(const QQuickScale);
210     return d->origin;
211 }
setOrigin(const QVector3D & point)212 void QQuickScale::setOrigin(const QVector3D &point)
213 {
214     Q_D(QQuickScale);
215     if (d->origin == point)
216         return;
217     d->origin = point;
218     update();
219     emit originChanged();
220 }
221 
222 /*!
223     \qmlproperty real QtQuick::Scale::xScale
224 
225     The scaling factor for the X axis.
226 
227     The default value is 1.0.
228 */
xScale() const229 qreal QQuickScale::xScale() const
230 {
231     Q_D(const QQuickScale);
232     return d->xScale;
233 }
setXScale(qreal scale)234 void QQuickScale::setXScale(qreal scale)
235 {
236     Q_D(QQuickScale);
237     if (d->xScale == scale)
238         return;
239     d->xScale = scale;
240     update();
241     emit xScaleChanged();
242     emit scaleChanged();
243 }
244 
245 /*!
246     \qmlproperty real QtQuick::Scale::yScale
247 
248     The scaling factor for the Y axis.
249 
250     The default value is 1.0.
251 */
yScale() const252 qreal QQuickScale::yScale() const
253 {
254     Q_D(const QQuickScale);
255     return d->yScale;
256 }
setYScale(qreal scale)257 void QQuickScale::setYScale(qreal scale)
258 {
259     Q_D(QQuickScale);
260     if (d->yScale == scale)
261         return;
262     d->yScale = scale;
263     update();
264     emit yScaleChanged();
265     emit scaleChanged();
266 }
267 
268 /*!
269     \qmlproperty real QtQuick::Scale::zScale
270     \internal
271 
272     The scaling factor for the Z axis.
273 
274     The default value is 1.0.
275 */
zScale() const276 qreal QQuickScale::zScale() const
277 {
278     Q_D(const QQuickScale);
279     return d->zScale;
280 }
setZScale(qreal scale)281 void QQuickScale::setZScale(qreal scale)
282 {
283     Q_D(QQuickScale);
284     if (d->zScale == scale)
285         return;
286     d->zScale = scale;
287     update();
288     emit zScaleChanged();
289     emit scaleChanged();
290 }
291 
applyTo(QMatrix4x4 * matrix) const292 void QQuickScale::applyTo(QMatrix4x4 *matrix) const
293 {
294     Q_D(const QQuickScale);
295     matrix->translate(d->origin);
296     matrix->scale(d->xScale, d->yScale, d->zScale);
297     matrix->translate(-d->origin);
298 }
299 
300 class QQuickRotationPrivate : public QQuickTransformPrivate
301 {
302 public:
QQuickRotationPrivate()303     QQuickRotationPrivate()
304         : angle(0), axis(0, 0, 1) {}
305     QVector3D origin;
306     qreal angle;
307     QVector3D axis;
308 };
309 
310 /*!
311     \qmltype Rotation
312     \instantiates QQuickRotation
313     \inqmlmodule QtQuick
314     \ingroup qtquick-visual-transforms
315     \brief Provides a way to rotate an Item.
316 
317     The Rotation type provides a way to rotate an \l Item through a
318     rotation-type transform.
319 
320     It allows (z axis) rotation to be relative to an arbitrary point, and also
321     provides a way to specify 3D-like rotations for Items. This gives more
322     control over item rotation than the \l{Item::}{rotation} property.
323 
324     The following example rotates a Rectangle around its interior point
325     (25, 25):
326 
327     \qml
328     Rectangle {
329         width: 100; height: 100
330         color: "blue"
331         transform: Rotation { origin.x: 25; origin.y: 25; angle: 45}
332     }
333     \endqml
334 
335     For 3D-like item rotations, you must specify the axis of rotation in
336     addition to the origin point. The following example shows various 3D-like
337     rotations applied to an \l Image.
338 
339     \snippet qml/rotation.qml 0
340 
341     \image axisrotation.png
342 
343     \sa {customitems/dialcontrol}{Dial Control example}, {Qt Quick Demo - Clocks}
344 */
QQuickRotation(QObject * parent)345 QQuickRotation::QQuickRotation(QObject *parent)
346     : QQuickTransform(*new QQuickRotationPrivate, parent)
347 {
348 }
349 
~QQuickRotation()350 QQuickRotation::~QQuickRotation()
351 {
352 }
353 
354 /*!
355     \qmlpropertygroup QtQuick::Rotation::origin
356     \qmlproperty real QtQuick::Rotation::origin.x
357     \qmlproperty real QtQuick::Rotation::origin.y
358 
359     The origin point of the rotation (i.e., the point that stays fixed
360     relative to the parent as the rest of the item rotates). By default
361     the origin is (0, 0).
362 */
origin() const363 QVector3D QQuickRotation::origin() const
364 {
365     Q_D(const QQuickRotation);
366     return d->origin;
367 }
368 
setOrigin(const QVector3D & point)369 void QQuickRotation::setOrigin(const QVector3D &point)
370 {
371     Q_D(QQuickRotation);
372     if (d->origin == point)
373         return;
374     d->origin = point;
375     update();
376     emit originChanged();
377 }
378 
379 /*!
380     \qmlproperty real QtQuick::Rotation::angle
381 
382     The angle to rotate, in degrees clockwise.
383 */
angle() const384 qreal QQuickRotation::angle() const
385 {
386     Q_D(const QQuickRotation);
387     return d->angle;
388 }
setAngle(qreal angle)389 void QQuickRotation::setAngle(qreal angle)
390 {
391     Q_D(QQuickRotation);
392     if (d->angle == angle)
393         return;
394     d->angle = angle;
395     update();
396     emit angleChanged();
397 }
398 
399 /*!
400     \qmlpropertygroup QtQuick::Rotation::axis
401     \qmlproperty real QtQuick::Rotation::axis.x
402     \qmlproperty real QtQuick::Rotation::axis.y
403     \qmlproperty real QtQuick::Rotation::axis.z
404 
405     The axis to rotate around. For simple (2D) rotation around a point, you
406     do not need to specify an axis, as the default axis is the z axis
407     (\c{ axis { x: 0; y: 0; z: 1 } }).
408 
409     For a typical 3D-like rotation you will usually specify both the origin
410     and the axis.
411 
412     \image 3d-rotation-axis.png
413 */
axis() const414 QVector3D QQuickRotation::axis() const
415 {
416     Q_D(const QQuickRotation);
417     return d->axis;
418 }
setAxis(const QVector3D & axis)419 void QQuickRotation::setAxis(const QVector3D &axis)
420 {
421     Q_D(QQuickRotation);
422     if (d->axis == axis)
423          return;
424     d->axis = axis;
425     update();
426     emit axisChanged();
427 }
428 
setAxis(Qt::Axis axis)429 void QQuickRotation::setAxis(Qt::Axis axis)
430 {
431     switch (axis)
432     {
433     case Qt::XAxis:
434         setAxis(QVector3D(1, 0, 0));
435         break;
436     case Qt::YAxis:
437         setAxis(QVector3D(0, 1, 0));
438         break;
439     case Qt::ZAxis:
440         setAxis(QVector3D(0, 0, 1));
441         break;
442     }
443 }
444 
445 class QGraphicsRotation {
446 public:
projectedRotate(QMatrix4x4 * matrix,qreal angle,qreal x,qreal y,qreal z)447     static inline void projectedRotate(QMatrix4x4 *matrix, qreal angle, qreal x, qreal y, qreal z)
448     {
449         matrix->projectedRotate(angle, x, y, z);
450     }
451 };
452 
applyTo(QMatrix4x4 * matrix) const453 void QQuickRotation::applyTo(QMatrix4x4 *matrix) const
454 {
455     Q_D(const QQuickRotation);
456 
457     if (d->angle == 0. || d->axis.isNull())
458         return;
459 
460     matrix->translate(d->origin);
461     QGraphicsRotation::projectedRotate(matrix, d->angle, d->axis.x(), d->axis.y(), d->axis.z());
462     matrix->translate(-d->origin);
463 }
464 
465 class QQuickMatrix4x4Private : public QQuickTransformPrivate
466 {
467 public:
QQuickMatrix4x4Private()468     QQuickMatrix4x4Private()
469         : matrix() {}
470     QMatrix4x4 matrix;
471 };
472 
473 /*!
474     \qmltype Matrix4x4
475     \instantiates QQuickMatrix4x4
476     \inqmlmodule QtQuick
477     \ingroup qtquick-visual-transforms
478     \since 5.3
479     \brief Provides a way to apply a 4x4 tranformation matrix to an \l Item.
480 
481     The Matrix4x4 type provides a way to apply a transformation to an
482     \l Item through a 4x4 matrix.
483 
484     It allows for a combination of rotation, scale, translatation and shearing
485     by using just one tranformation provided in a 4x4-matrix.
486 
487     The following example rotates a Rectangle 45 degress (PI/4):
488 
489     \qml
490     Rectangle {
491         width: 100
492         height: 100
493         color: "red"
494 
495         transform: Matrix4x4 {
496             property real a: Math.PI / 4
497             matrix: Qt.matrix4x4(Math.cos(a), -Math.sin(a), 0, 0,
498                                  Math.sin(a),  Math.cos(a), 0, 0,
499                                  0,           0,            1, 0,
500                                  0,           0,            0, 1)
501         }
502     }
503     \endqml
504 */
QQuickMatrix4x4(QObject * parent)505 QQuickMatrix4x4::QQuickMatrix4x4(QObject *parent)
506     : QQuickTransform(*new QQuickMatrix4x4Private, parent)
507 {
508 }
509 
~QQuickMatrix4x4()510 QQuickMatrix4x4::~QQuickMatrix4x4()
511 {
512 }
513 
514 /*!
515     \qmlproperty QMatrix4x4 QtQuick::Matrix4x4::matrix
516 
517     4x4-matrix which will be used in the tranformation of an \l Item
518 */
matrix() const519 QMatrix4x4 QQuickMatrix4x4::matrix() const
520 {
521     Q_D(const QQuickMatrix4x4);
522     return d->matrix;
523 }
524 
setMatrix(const QMatrix4x4 & matrix)525 void QQuickMatrix4x4::setMatrix(const QMatrix4x4 &matrix)
526 {
527     Q_D(QQuickMatrix4x4);
528     if (d->matrix == matrix)
529          return;
530     d->matrix = matrix;
531     update();
532     emit matrixChanged();
533 }
534 
applyTo(QMatrix4x4 * matrix) const535 void QQuickMatrix4x4::applyTo(QMatrix4x4 *matrix) const
536 {
537     Q_D(const QQuickMatrix4x4);
538     *matrix *= d->matrix;
539 }
540 
541 QT_END_NAMESPACE
542 
543 #include "moc_qquicktranslate_p.cpp"
544